]> git.basschouten.com Git - openhab-addons.git/blob
668723322e246c40ed3c7ea7d00afbf59a4bc81e
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.io.hueemulation.internal.upnp;
14
15 import static org.hamcrest.CoreMatchers.is;
16 import static org.junit.Assert.*;
17 import static org.mockito.Mockito.mock;
18
19 import java.io.IOException;
20 import java.net.DatagramPacket;
21 import java.net.DatagramSocket;
22 import java.util.concurrent.ExecutionException;
23 import java.util.concurrent.Executor;
24 import java.util.concurrent.TimeUnit;
25 import java.util.concurrent.TimeoutException;
26
27 import javax.ws.rs.core.Response;
28
29 import org.glassfish.grizzly.osgi.httpservice.HttpServiceImpl;
30 import org.glassfish.grizzly.osgi.httpservice.OSGiMainHandler;
31 import org.glassfish.grizzly.osgi.httpservice.util.Logger;
32 import org.glassfish.jersey.server.ResourceConfig;
33 import org.hamcrest.CoreMatchers;
34 import org.junit.After;
35 import org.junit.AfterClass;
36 import org.junit.Before;
37 import org.junit.BeforeClass;
38 import org.junit.Test;
39 import org.mockito.ArgumentMatchers;
40 import org.mockito.Mockito;
41 import org.openhab.io.hueemulation.internal.rest.CommonSetup;
42 import org.openhab.io.hueemulation.internal.rest.LightsAndGroups;
43 import org.osgi.framework.Bundle;
44 import org.osgi.util.tracker.ServiceTracker;
45
46 /**
47  * Tests the upnp server part if the description.xml is available and if the udp thread comes online
48  *
49  * @author David Graeff - Initial contribution
50  */
51 public class UpnpTests {
52     protected static CommonSetup commonSetup = null;
53     protected UpnpServer subject;
54     protected static OSGiMainHandler mainHttpHandler;
55     private static HttpServiceImpl httpServiceImpl;
56     private static String descriptionPath;
57
58     LightsAndGroups lightsAndGroups = new LightsAndGroups();
59
60     @BeforeClass
61     public static void setupHttpParts() throws IOException {
62         commonSetup = new CommonSetup(true);
63         commonSetup.start(new ResourceConfig());
64
65         descriptionPath = commonSetup.basePath.replace("/api", "/description.xml");
66
67         Logger logger = new org.glassfish.grizzly.osgi.httpservice.util.Logger(mock(ServiceTracker.class));
68
69         mainHttpHandler = new OSGiMainHandler(logger, mock(Bundle.class));
70         commonSetup.server.getServerConfiguration().addHttpHandler(mainHttpHandler, "/");
71
72         httpServiceImpl = new HttpServiceImpl(mock(Bundle.class), logger);
73     }
74
75     @Before
76     public void setup() {
77         Executor executor = mock(Executor.class);
78         Mockito.doAnswer(a -> {
79             ((Runnable) a.getArgument(0)).run();
80             return null;
81         }).when(executor).execute(ArgumentMatchers.any());
82         subject = new UpnpServer(executor);
83         subject.httpService = httpServiceImpl;
84         subject.cs = commonSetup.cs;
85         subject.overwriteReadyToFalse = true;
86         subject.activate(); // don't execute handleEvent()
87         subject.overwriteReadyToFalse = false;
88     }
89
90     @After
91     public void tearDown() {
92         subject.deactivate();
93     }
94
95     @AfterClass
96     public static void tearDownHttp() {
97         mainHttpHandler.unregisterAll();
98         commonSetup.dispose();
99     }
100
101     @Test
102     public void descriptionWithoutAddress() {
103         Response response = commonSetup.client.target(descriptionPath).request().get();
104         assertEquals(404, response.getStatus());
105     }
106
107     @Test
108     public void descriptionWithAddress()
109             throws InterruptedException, ExecutionException, TimeoutException, IOException {
110         HueEmulationConfigWithRuntime r = subject.createConfiguration(null);
111         r = subject.performAddressTest(r);
112         subject.applyConfiguration(r);
113         Response response = commonSetup.client.target(descriptionPath).request().get();
114         assertEquals(200, response.getStatus());
115         String body = response.readEntity(String.class);
116         assertThat(body, is(subject.xmlDocWithAddress));
117
118         if (r == null) {
119             throw new IllegalStateException();
120         }
121
122         // UDP thread started?
123         r.startNow(r).get(5, TimeUnit.SECONDS);
124         assertThat(subject.upnpAnnouncementThreadRunning(), is(true));
125
126         // Send M-SEARCH UPNP "packet" and check if the result contains our bridge ID
127         try (DatagramSocket sendSocket = new DatagramSocket()) {
128             sendSocket.setSoTimeout(700);
129             byte[] bytes = "M-SEARCH".getBytes();
130             sendSocket.send(new DatagramPacket(bytes, bytes.length, subject.MULTI_ADDR_IPV4, UpnpServer.UPNP_PORT));
131             byte[] buffer = new byte[1000];
132             DatagramPacket p = new DatagramPacket(buffer, buffer.length);
133             sendSocket.receive(p);
134             String received = new String(buffer);
135             assertThat(received, CoreMatchers.startsWith("HTTP/1.1 200 OK"));
136             assertThat(received, CoreMatchers.containsString("hue-bridgeid: DEMOUUID"));
137         }
138
139         r.dispose();
140         assertThat(subject.upnpAnnouncementThreadRunning(), is(false));
141     }
142
143     @Test
144     public void handEventTest() throws InterruptedException, ExecutionException, TimeoutException {
145         subject.handleEvent(null);
146         subject.configChangeFuture.get(5, TimeUnit.SECONDS);
147         assertThat(subject.upnpAnnouncementThreadRunning(), is(true));
148
149         subject.deactivate();
150         assertThat(subject.upnpAnnouncementThreadRunning(), is(false));
151     }
152 }