server: Fix use of DLNA.ORG_AnyContainer
[profile/ivi/rygel.git] / tests / rygel-http-time-seek-test.vala
1 /*
2  * Copyright (C) 2010 Nokia Corporation.
3  *
4  * Author: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
5  *                               <zeeshanak@gnome.org>
6  *
7  * This file is part of Rygel.
8  *
9  * Rygel is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Rygel is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  */
23
24 private errordomain Rygel.TestError {
25     SKIP
26 }
27
28 private class Rygel.HTTPTranscodeHandler : GLib.Object {}
29
30 public class Rygel.MediaObject : GLib.Object {
31     public int64 size = -1;
32 }
33
34 public class Rygel.MediaContainer : MediaObject {
35 }
36
37 private abstract class Rygel.MediaItem : MediaObject {
38     public bool is_live_stream () {
39         return true;
40     }
41 }
42
43 private class Rygel.AudioItem : MediaItem {
44     public int64 duration = 2048;
45 }
46
47 private class Rygel.Thumbnail : GLib.Object {}
48 private class Rygel.Subtitle : GLib.Object {}
49
50 private class Rygel.HTTPGet : GLib.Object {
51     public const string ITEM_URI = "http://DoesntMatterWhatThisIs";
52
53     public Soup.Message msg;
54     public MediaObject object;
55     public Thumbnail thumbnail;
56     public Subtitle subtitle;
57
58     public HTTPTranscodeHandler handler;
59
60     public HTTPGet (Thumbnail? thumbnail, Subtitle? subtitle) {
61         this.msg = new Soup.Message ("HTTP", ITEM_URI);
62         this.object = new AudioItem ();
63         this.handler = new HTTPTranscodeHandler ();
64         this.thumbnail = thumbnail;
65         this.subtitle = subtitle;
66     }
67
68     public HTTPGet.seek_start (int64      start,
69                                Thumbnail? thumbnail,
70                                Subtitle?  subtitle) {
71         this (thumbnail, subtitle);
72
73         this.add_headers (start, -1);
74     }
75
76     public HTTPGet.seek_stop (int64      stop,
77                               Thumbnail? thumbnail,
78                               Subtitle?  subtitle) {
79         this (thumbnail, subtitle);
80
81         this.add_headers (0, stop);
82     }
83
84     public HTTPGet.seek_start_stop (int64      start,
85                                     int64      stop,
86                                     Thumbnail? thumbnail,
87                                     Subtitle?  subtitle) {
88         this (thumbnail, subtitle);
89
90         this.add_headers (start, stop);
91     }
92
93     public HTTPGet.seek_strings (string     start,
94                                  string     stop,
95                                  Thumbnail? thumbnail,
96                                  Subtitle?  subtitle) {
97         this (thumbnail, subtitle);
98
99         this.add_string_headers (start, stop);
100     }
101
102     private void add_headers (int64 start, int64 stop) requires (start >= 0) {
103         var stop_str = (stop > 0)? stop.to_string (): "";
104         var range = "npt=" + start.to_string () + "-" + stop_str;
105         this.msg.request_headers.append ("TimeSeekRange.dlna.org", range);
106     }
107
108     private void add_string_headers (string start, string stop) {
109         var range = "npt=" + start + "-" + stop;
110         this.msg.request_headers.append ("TimeSeekRange.dlna.org", range);
111     }
112 }
113
114 private class Rygel.HTTPTimeSeekTest : GLib.Object {
115     private Regex range_regex;
116
117     enum TestType {
118         TEST_SECONDS_PARSING,
119         TEST_HHMMSS_PARSING,
120         TEST_MIXED_PARSING
121     }
122     private TestType test_type;
123
124     public static int main (string[] args) {
125         try {
126             var test = new HTTPTimeSeekTest ();
127
128             test.run ();
129         /* TODO: Nothing throws this exception. Should it?
130         } catch (TestError.SKIP error) {
131             return 77;
132         */
133         } catch (Error error) {
134             critical ("%s", error.message);
135
136             return -1;
137         }
138
139         return 0;
140     }
141
142     public void run () throws HTTPSeekError {
143         var thumbnails = new Thumbnail[] { null, new Thumbnail () };
144         var subtitles = new Subtitle[] { null, new Subtitle () };
145
146         foreach (var thumbnail in thumbnails) {
147             foreach (var subtitle in subtitles) {
148                 this.test_type = TestType.TEST_SECONDS_PARSING;
149                 this.test_no_seek (thumbnail, subtitle);
150                 this.test_start_only_seek (thumbnail, subtitle);
151                 this.test_stop_only_seek (thumbnail, subtitle);
152                 this.test_start_stop_seek (thumbnail, subtitle);
153                 this.test_type = TestType.TEST_HHMMSS_PARSING;
154                 this.test_start_only_seek (thumbnail, subtitle);
155                 this.test_stop_only_seek (thumbnail, subtitle);
156                 this.test_start_stop_seek (thumbnail, subtitle);
157                 this.test_type = TestType.TEST_MIXED_PARSING;
158                 this.test_start_stop_seek (thumbnail, subtitle);
159             }
160         }
161     }
162
163     private HTTPTimeSeekTest () {
164         var expression = "npt=[0-9]+\\.[0-9][0-9][0-9]-" +
165                          "[0-9]+\\.[0-9][0-9][0-9]/" +
166                          "[0-9]+\\.[0-9][0-9][0-9]";
167
168         try {
169             this.range_regex = new Regex (expression, RegexCompileFlags.CASELESS);
170         } catch (RegexError error) {
171             // This means that it is not a regular expression
172             assert_not_reached ();
173         }
174     }
175
176     private void test_no_seek (Thumbnail? thumbnail,
177                                Subtitle?  subtitle) throws HTTPSeekError {
178         var request = new HTTPGet (thumbnail, subtitle);
179         var audio_item = request.object as AudioItem;
180         this.test_seek (request,
181                         0,
182                         audio_item.duration * TimeSpan.SECOND - TimeSpan.MILLISECOND);
183     }
184
185     private void test_start_only_seek (Thumbnail? thumbnail,
186                                        Subtitle?  subtitle)
187                                        throws HTTPSeekError {
188         HTTPGet request = null;
189
190         switch (this.test_type) {
191         case TestType.TEST_SECONDS_PARSING:
192             request = new HTTPGet.seek_start (128, thumbnail, subtitle);
193
194             break;
195
196         case TestType.TEST_HHMMSS_PARSING:
197             request = new HTTPGet.seek_strings ("00:02:08.000", "", thumbnail, subtitle);
198
199             break;
200         }
201
202         var audio_item = request.object as AudioItem;
203         this.test_seek (request,
204                         128 * TimeSpan.SECOND,
205                         audio_item.duration * TimeSpan.SECOND - TimeSpan.MILLISECOND);
206     }
207
208     private void test_stop_only_seek (Thumbnail? thumbnail,
209                                       Subtitle?  subtitle)
210                                       throws HTTPSeekError {
211         HTTPGet request = null;
212
213         switch (this.test_type) {
214         case TestType.TEST_SECONDS_PARSING:
215             request = new HTTPGet.seek_stop (128, thumbnail, subtitle);
216
217             break;
218
219         case TestType.TEST_HHMMSS_PARSING:
220             request = new HTTPGet.seek_strings ("00:00:00.000",
221                                                 "00:02:08.000",
222                                                 thumbnail,
223                                                 subtitle);
224
225             break;
226         }
227
228         this.test_seek (request, 0, 128 * TimeSpan.SECOND);
229     }
230
231     private void test_start_stop_seek (Thumbnail? thumbnail,
232                                        Subtitle?  subtitle)
233                                        throws HTTPSeekError {
234         HTTPGet request = null;
235
236         switch (this.test_type) {
237         case TestType.TEST_SECONDS_PARSING:
238             request = new HTTPGet.seek_start_stop (128,
239                                                    256,
240                                                    thumbnail,
241                                                    subtitle);
242
243             break;
244
245         case TestType.TEST_HHMMSS_PARSING:
246             request = new HTTPGet.seek_strings ("00:02:08.000",
247                                                 "00:04:16.000",
248                                                 thumbnail,
249                                                 subtitle);
250
251             break;
252
253         case TestType.TEST_MIXED_PARSING:
254             request = new HTTPGet.seek_strings ("00:02:08.000",
255                                                 "256.000",
256                                                 thumbnail,
257                                                 subtitle);
258
259             break;
260         }
261
262
263         this.test_seek (request, 128 * TimeSpan.SECOND, 256 * TimeSpan.SECOND);
264     }
265
266     private void test_seek (HTTPGet request,
267                             int64   start,
268                             int64   stop) throws HTTPSeekError {
269         assert (HTTPTimeSeek.needed (request));
270
271         var seek = new HTTPTimeSeek (request);
272         seek.add_response_headers ();
273
274         assert (seek != null);
275         assert (seek.start == start);
276         assert (seek.stop == stop);
277         assert (seek.length == seek.stop + TimeSpan.MILLISECOND - seek.start);
278
279         var audio_item = request.object as AudioItem;
280         assert (seek.total_length == audio_item.duration * TimeSpan.SECOND);
281
282         var header = request.msg.response_headers.get_one
283                                         ("TimeSeekRange.dlna.org");
284         assert (header != null);
285         assert (this.range_regex.match (header));
286
287         /* TODO: This is just here to avoid a warning about
288          * requested() not being used.
289          * How should this really be tested?
290          * Sometimes the result here is true, and sometimes it is false.
291          */
292         /* bool result = */ HTTPTimeSeek.requested(request);
293     }
294 }