1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.fourthline.cling.test.control;
17
18 import org.fourthline.cling.controlpoint.ActionCallback;
19 import org.fourthline.cling.mock.MockRouter;
20 import org.fourthline.cling.mock.MockUpnpService;
21 import org.fourthline.cling.model.action.ActionInvocation;
22 import org.fourthline.cling.model.message.StreamRequestMessage;
23 import org.fourthline.cling.model.message.StreamResponseMessage;
24 import org.fourthline.cling.model.message.UpnpHeaders;
25 import org.fourthline.cling.model.message.UpnpResponse;
26 import org.fourthline.cling.model.message.header.ContentTypeHeader;
27 import org.fourthline.cling.model.message.header.SoapActionHeader;
28 import org.fourthline.cling.model.message.header.UpnpHeader;
29 import org.fourthline.cling.model.meta.Action;
30 import org.fourthline.cling.model.meta.ActionArgument;
31 import org.fourthline.cling.model.meta.DeviceDetails;
32 import org.fourthline.cling.model.meta.LocalDevice;
33 import org.fourthline.cling.model.meta.LocalService;
34 import org.fourthline.cling.model.meta.RemoteDevice;
35 import org.fourthline.cling.model.meta.RemoteService;
36 import org.fourthline.cling.model.meta.Service;
37 import org.fourthline.cling.model.meta.StateVariable;
38 import org.fourthline.cling.model.meta.StateVariableEventDetails;
39 import org.fourthline.cling.model.meta.StateVariableTypeDetails;
40 import org.fourthline.cling.model.profile.ClientInfo;
41 import org.fourthline.cling.model.types.Datatype;
42 import org.fourthline.cling.model.types.ErrorCode;
43 import org.fourthline.cling.model.types.UDADeviceType;
44 import org.fourthline.cling.model.types.UDAServiceId;
45 import org.fourthline.cling.model.types.UDAServiceType;
46 import org.fourthline.cling.model.types.UnsignedIntegerFourBytes;
47 import org.fourthline.cling.test.data.SampleData;
48 import org.fourthline.cling.test.data.SampleServiceOne;
49 import org.fourthline.cling.transport.RouterException;
50 import org.testng.annotations.Test;
51
52 import java.net.URI;
53 import java.util.Arrays;
54
55 import static org.testng.Assert.assertEquals;
56
57
58 public class ActionInvokeOutgoingTest {
59
60 public static final String RESPONSE_SUCCESSFUL = "<?xml version=\"1.0\"?>\n" +
61 " <s:Envelope\n" +
62 " xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
63 " s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" +
64 " <s:Body>\n" +
65 " <u:GetTargetResponse xmlns:u=\"urn:schemas-upnp-org:service:SwitchPower:1\">\n" +
66 " <RetTargetValue>0</RetTargetValue>\n" +
67 " </u:GetTargetResponse>\n" +
68 " </s:Body>\n" +
69 " </s:Envelope>";
70
71 public static final String RESPONSE_QUERY_VARIABLE = "<?xml version=\"1.0\"?>\n" +
72 " <s:Envelope\n" +
73 " xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
74 " s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" +
75 " <s:Body>\n" +
76 " <u:QueryStateVariableResponse xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\n" +
77 " <return>0</return>\n" +
78 " </u:QueryStateVariableResponse>\n" +
79 " </s:Body>\n" +
80 " </s:Envelope>";
81
82 public static final String RESPONSE_FAILURE = "<?xml version=\"1.0\"?>\n" +
83 " <s:Envelope\n" +
84 " xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
85 " s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" +
86 " <s:Body>\n" +
87 " <s:Fault>\n" +
88 " <faultcode>s:Client</faultcode>\n" +
89 " <faultstring>UPnPError</faultstring>\n" +
90 " <detail>\n" +
91 " <UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">\n" +
92 " <errorCode>611</errorCode>\n" +
93 " <errorDescription>A test string</errorDescription>\n" +
94 " </UPnPError>\n" +
95 " </detail>\n" +
96 " </s:Fault>\n" +
97 " </s:Body>\n" +
98 " </s:Envelope>";
99
100 public static final String RESPONSE_NEGATIVE_VALUE = "<?xml version=\"1.0\"?>\n" +
101 " <s:Envelope\n" +
102 " xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
103 " s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" +
104 " <s:Body>\n" +
105 " <u:GetNegativeValueResponse xmlns:u=\"urn:schemas-upnp-org:service:MyService:1\">\n" +
106 " <Result>-1</Result>\n" +
107 " </u:GetNegativeValueResponse>\n" +
108 " </s:Body>\n" +
109 " </s:Envelope>";
110
111 @Test
112 public void callLocalGet() throws Exception {
113
114
115 MockUpnpService upnpService = new MockUpnpService();
116 LocalDevice ld = ActionSampleData.createTestDevice();
117 LocalService service = ld.getServices()[0];
118 upnpService.getRegistry().addDevice(ld);
119
120 Action action = service.getAction("GetTarget");
121 ActionInvocation actionInvocation = new ActionInvocation(action);
122
123 final boolean[] assertions = new boolean[1];
124 ActionCallback callback = new ActionCallback(actionInvocation) {
125 @Override
126 public void success(ActionInvocation invocation) {
127 assertions[0] = true;
128 }
129
130 @Override
131 public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {
132 assertions[0] = false;
133 }
134
135 };
136
137 upnpService.getControlPoint().execute(callback);
138
139 assert actionInvocation.getFailure() == null;
140 assertEquals(upnpService.getRouter().getSentStreamRequestMessages().size(), 0);
141 assertEquals(assertions[0], true);
142 assertEquals(actionInvocation.getOutput().length, 1);
143 assertEquals(actionInvocation.getOutput()[0].toString(), "0");
144
145 }
146
147
148 @Test
149 public void callLocalWrongAction() throws Exception {
150
151
152 MockUpnpService upnpService = new MockUpnpService();
153 LocalDevice ld = ActionSampleData.createTestDevice();
154 LocalService service = ld.getServices()[0];
155 upnpService.getRegistry().addDevice(ld);
156
157 assertEquals(service.getAction("NonExistentAction"), null);
158 }
159
160 @Test
161 public void callLocalSetException() throws Exception {
162
163
164 MockUpnpService upnpService = new MockUpnpService();
165 LocalDevice ld = ActionSampleData.createTestDevice(ActionSampleData.LocalTestServiceThrowsException.class);
166 LocalService service = ld.getServices()[0];
167 upnpService.getRegistry().addDevice(ld);
168
169 Action action = service.getAction("SetTarget");
170 ActionInvocation actionInvocation = new ActionInvocation(action);
171
172 actionInvocation.setInput("NewTargetValue", true);
173
174 final boolean[] assertions = new boolean[1];
175 ActionCallback callback = new ActionCallback(actionInvocation) {
176 @Override
177 public void success(ActionInvocation invocation) {
178 assertions[0] = false;
179 }
180
181 @Override
182 public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {
183 assert operation == null;
184 assertions[0] = true;
185 }
186 };
187
188 upnpService.getControlPoint().execute(callback);
189
190 assert actionInvocation.getFailure() != null;
191 assertEquals(upnpService.getRouter().getSentStreamRequestMessages().size(), 0);
192 assertEquals(assertions[0], true);
193
194 assertEquals(actionInvocation.getFailure().getErrorCode(), ErrorCode.ACTION_FAILED.getCode());
195 assertEquals(
196 actionInvocation.getFailure().getMessage(),
197 ErrorCode.ACTION_FAILED.getDescription() + ". Something is wrong."
198 );
199 }
200
201 @Test
202 public void callRemoteGet() throws Exception {
203
204 MockUpnpService upnpService = new MockUpnpService() {
205 @Override
206 protected MockRouter createRouter() {
207 return new MockRouter(getConfiguration(), getProtocolFactory()) {
208
209 @Override
210 public StreamResponseMessage send(StreamRequestMessage msg) throws RouterException {
211 return super.send(msg);
212 }
213
214 @Override
215 public StreamResponseMessage[] getStreamResponseMessages() {
216 return new StreamResponseMessage[]{
217 new StreamResponseMessage(RESPONSE_SUCCESSFUL)
218 };
219 }
220 };
221 }
222 };
223
224
225 RemoteDevice device = SampleData.createRemoteDevice();
226 Service service = SampleData.getFirstService(device);
227 upnpService.getRegistry().addDevice(device);
228
229 Action action = service.getAction("GetTarget");
230
231 UpnpHeaders extraHeaders = new UpnpHeaders();
232 extraHeaders.add(UpnpHeader.Type.USER_AGENT.getHttpName(), "MyCustom/Agent");
233 extraHeaders.add("X-Custom-Header", "foo");
234
235 ActionInvocation actionInvocation =
236 new ActionInvocation(
237 action,
238 new ClientInfo(extraHeaders)
239 );
240
241 final boolean[] assertions = new boolean[1];
242 ActionCallback callback = new ActionCallback(actionInvocation) {
243 @Override
244 public void success(ActionInvocation invocation) {
245 assertions[0] = true;
246 }
247
248 @Override
249 public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {
250 assertions[0] = false;
251 }
252 };
253
254 upnpService.getControlPoint().execute(callback);
255
256 assert actionInvocation.getFailure() == null;
257 assertEquals(upnpService.getRouter().getSentStreamRequestMessages().size(), 1);
258 assertEquals(assertions[0], true);
259
260 StreamRequestMessage request = upnpService.getRouter().getSentStreamRequestMessages().get(0);
261
262
263 assertEquals(
264 request.getHeaders().getFirstHeaderString(UpnpHeader.Type.CONTENT_TYPE),
265 ContentTypeHeader.DEFAULT_CONTENT_TYPE_UTF8.toString()
266 );
267 assertEquals(
268 request.getHeaders().getFirstHeaderString(UpnpHeader.Type.SOAPACTION),
269 "\"" + SampleServiceOne.getThisServiceType().toString() + "#GetTarget\""
270 );
271
272
273 assertEquals(
274 request.getHeaders().getFirstHeaderString(UpnpHeader.Type.USER_AGENT),
275 "MyCustom/Agent"
276 );
277 assertEquals(
278 request.getHeaders().getFirstHeader("X-CUSTOM-HEADER"),
279 "foo"
280 );
281
282 assertEquals(actionInvocation.getOutput().length, 1);
283 assertEquals(actionInvocation.getOutput()[0].toString(), "0");
284
285 }
286
287 @Test
288 public void callRemoteGetFailure() throws Exception {
289
290 MockUpnpService upnpService = new MockUpnpService() {
291 @Override
292 protected MockRouter createRouter() {
293 return new MockRouter(getConfiguration(), getProtocolFactory()) {
294 @Override
295 public StreamResponseMessage[] getStreamResponseMessages() {
296 return new StreamResponseMessage[]{
297 new StreamResponseMessage(new UpnpResponse(UpnpResponse.Status.INTERNAL_SERVER_ERROR), RESPONSE_FAILURE)
298 };
299 }
300 };
301 }
302 };
303
304
305 RemoteDevice device = SampleData.createRemoteDevice();
306 Service service = SampleData.getFirstService(device);
307 upnpService.getRegistry().addDevice(device);
308
309 Action action = service.getAction("GetTarget");
310
311 ActionInvocation actionInvocation = new ActionInvocation(action);
312 final boolean[] assertions = new boolean[1];
313 ActionCallback callback = new ActionCallback(actionInvocation) {
314 @Override
315 public void success(ActionInvocation invocation) {
316 assertions[0] = false;
317 }
318
319 @Override
320 public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {
321 assertEquals(operation.getStatusCode(), UpnpResponse.Status.INTERNAL_SERVER_ERROR.getStatusCode());
322 assertions[0] = true;
323 }
324 };
325
326 upnpService.getControlPoint().execute(callback);
327
328 assert actionInvocation.getFailure() != null;
329 assertEquals(upnpService.getRouter().getSentStreamRequestMessages().size(), 1);
330 assertEquals(assertions[0], true);
331 assertEquals(actionInvocation.getFailure().getErrorCode(), ErrorCode.INVALID_CONTROL_URL.getCode());
332 assertEquals(
333 actionInvocation.getFailure().getMessage(),
334 "A test string"
335 );
336
337 }
338
339 @Test
340 public void callRemoteGetNotFoundFailure() throws Exception {
341
342 MockUpnpService upnpService = new MockUpnpService() {
343 @Override
344 protected MockRouter createRouter() {
345 return new MockRouter(getConfiguration(), getProtocolFactory()) {
346 @Override
347 public StreamResponseMessage[] getStreamResponseMessages() {
348 return new StreamResponseMessage[]{
349 new StreamResponseMessage(new UpnpResponse(UpnpResponse.Status.NOT_FOUND))
350 };
351 }
352 };
353 }
354 };
355
356
357 RemoteDevice device = SampleData.createRemoteDevice();
358 Service service = SampleData.getFirstService(device);
359 upnpService.getRegistry().addDevice(device);
360
361 Action action = service.getAction("GetTarget");
362
363 ActionInvocation actionInvocation = new ActionInvocation(action);
364 final boolean[] assertions = new boolean[1];
365 ActionCallback callback = new ActionCallback(actionInvocation) {
366 @Override
367 public void success(ActionInvocation invocation) {
368 assertions[0] = false;
369 }
370
371 @Override
372 public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {
373 assertEquals(operation.getStatusCode(), UpnpResponse.Status.NOT_FOUND.getStatusCode());
374 assertions[0] = true;
375 }
376 };
377
378 upnpService.getControlPoint().execute(callback);
379
380 assert actionInvocation.getFailure() != null;
381 assertEquals(upnpService.getRouter().getSentStreamRequestMessages().size(), 1);
382 assertEquals(assertions[0], true);
383 assertEquals(actionInvocation.getFailure().getErrorCode(), ErrorCode.ACTION_FAILED.getCode());
384 assertEquals(
385 actionInvocation.getFailure().getMessage(),
386 ErrorCode.ACTION_FAILED.getDescription() + ". Non-recoverable remote execution failure: 404 Not Found."
387 );
388
389 }
390
391 @Test
392 public void callRemoteGetNoResponse() throws Exception {
393
394 MockUpnpService upnpService = new MockUpnpService();
395
396
397 RemoteDevice device = SampleData.createRemoteDevice();
398 Service service = SampleData.getFirstService(device);
399 upnpService.getRegistry().addDevice(device);
400
401 Action action = service.getAction("GetTarget");
402
403 ActionInvocation actionInvocation = new ActionInvocation(action);
404 final boolean[] assertions = new boolean[1];
405 ActionCallback callback = new ActionCallback(actionInvocation) {
406 @Override
407 public void success(ActionInvocation invocation) {
408 assertions[0] = false;
409 }
410
411 @Override
412 public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {
413 assert operation == null;
414 assertions[0] = true;
415 }
416 };
417
418 upnpService.getControlPoint().execute(callback);
419
420 assert actionInvocation.getFailure() != null;
421 assertEquals(upnpService.getRouter().getSentStreamRequestMessages().size(), 1);
422 assertEquals(assertions[0], true);
423 assertEquals(actionInvocation.getFailure().getErrorCode(), ErrorCode.ACTION_FAILED.getCode());
424 assertEquals(
425 actionInvocation.getFailure().getMessage(),
426 ErrorCode.ACTION_FAILED.getDescription() + ". Connection error or no response received."
427 );
428 }
429
430 @Test
431 public void callRemoteNegativeValue() throws Exception {
432
433 MockUpnpService upnpService = new MockUpnpService() {
434 @Override
435 protected MockRouter createRouter() {
436 return new MockRouter(getConfiguration(), getProtocolFactory()) {
437 @Override
438 public StreamResponseMessage[] getStreamResponseMessages() {
439 return new StreamResponseMessage[]{
440 new StreamResponseMessage(RESPONSE_NEGATIVE_VALUE)
441 };
442 }
443 };
444 }
445 };
446
447
448 RemoteDevice device = new RemoteDevice(
449 SampleData.createRemoteDeviceIdentity(),
450 new UDADeviceType("MyDevice"),
451 new DeviceDetails("JustATest"),
452 new RemoteService(
453 new UDAServiceType("MyService"),
454 new UDAServiceId("MyService"),
455 URI.create("/scpd.xml"),
456 URI.create("/control"),
457 URI.create("/events"),
458 new Action[]{
459 new Action(
460 "GetNegativeValue",
461 new ActionArgument[]{
462 new ActionArgument("Result", "NegativeValue", ActionArgument.Direction.OUT)
463 }
464 )
465 },
466 new StateVariable[]{
467 new StateVariable(
468 "NegativeValue",
469 new StateVariableTypeDetails(Datatype.Builtin.UI4.getDatatype()),
470 new StateVariableEventDetails(false)
471 )
472 }
473 )
474 );
475
476 upnpService.getRegistry().addDevice(device);
477
478 Action action = device.getServices()[0].getAction("GetNegativeValue");
479
480 ActionInvocation actionInvocation = new ActionInvocation(action);
481 final boolean[] assertions = new boolean[1];
482 ActionCallback callback = new ActionCallback(actionInvocation) {
483 @Override
484 public void success(ActionInvocation invocation) {
485 assertions[0] = true;
486 }
487
488 @Override
489 public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {
490 assertions[0] = false;
491 }
492 };
493
494 upnpService.getControlPoint().execute(callback);
495
496 assert actionInvocation.getFailure() == null;
497
498 assertEquals(actionInvocation.getOutput("Result").getValue(), new UnsignedIntegerFourBytes(0));
499 }
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631 @Test
632 public void callRemoteQueryStateVariable() throws Exception {
633
634 MockUpnpService upnpService = new MockUpnpService() {
635 @Override
636 protected MockRouter createRouter() {
637 return new MockRouter(getConfiguration(), getProtocolFactory()) {
638 @Override
639 public StreamResponseMessage[] getStreamResponseMessages() {
640 return new StreamResponseMessage[]{
641 new StreamResponseMessage(RESPONSE_QUERY_VARIABLE)
642 };
643 }
644 };
645 }
646 };
647
648
649 RemoteDevice device = SampleData.createRemoteDevice();
650 Service service = SampleData.getFirstService(device);
651 upnpService.getRegistry().addDevice(device);
652
653 Action action = service.getQueryStateVariableAction();
654 ActionInvocation actionInvocation = new ActionInvocation(action);
655 actionInvocation.setInput("varName", "Target");
656
657 final boolean[] assertions = new boolean[1];
658 ActionCallback callback = new ActionCallback(actionInvocation) {
659 @Override
660 public void success(ActionInvocation invocation) {
661 assertions[0] = true;
662 }
663
664 @Override
665 public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {
666 assertions[0] = false;
667 }
668 };
669
670 upnpService.getControlPoint().execute(callback);
671
672 assert actionInvocation.getFailure() == null;
673 assertEquals(upnpService.getRouter().getSentStreamRequestMessages().size(), 1);
674 assertEquals(assertions[0], true);
675 assertEquals(
676 upnpService.getRouter().getSentStreamRequestMessages().get(0).getHeaders().getFirstHeader(UpnpHeader.Type.CONTENT_TYPE, ContentTypeHeader.class).getString(),
677 ContentTypeHeader.DEFAULT_CONTENT_TYPE_UTF8.toString()
678 );
679 assertEquals(
680 upnpService.getRouter().getSentStreamRequestMessages().get(0).getHeaders().getFirstHeader(UpnpHeader.Type.SOAPACTION, SoapActionHeader.class).getString(),
681 "\"urn:schemas-upnp-org:control-1-0#QueryStateVariable\""
682 );
683 assertEquals(actionInvocation.getOutput().length, 1);
684 assertEquals(actionInvocation.getOutput()[0].getArgument().getName(), "return");
685 assertEquals(actionInvocation.getOutput()[0].toString(), "0");
686 }
687
688
689 }