Assamese translation updated
[profile/ivi/rygel.git] / tests / rygel-http-get-test.vala
index 3332305..3893e08 100644 (file)
@@ -34,15 +34,43 @@ public errordomain Rygel.ClientHacksError {
 }
 
 public class Rygel.ClientHacks {
-    public static ClientHacks create_for_headers (MessageHeaders headers) throws Error {
-        throw new ClientHacksError.NA ("");
+    public static ClientHacks create (Message? message) throws Error {
+        var headers = message.request_headers;
+        if (headers.get_one ("clienthacks.test.rygel") != null) {
+            return new ClientHacks ();
+        } else {
+            throw new ClientHacksError.NA ("");
+        }
+    }
+
+    public void apply (MediaObject? item) {
     }
 
-    public bool is_album_art_request (Message message) {
+    public bool force_seek () {
         return false;
     }
 }
 
+public class Rygel.TestRequestFactory {
+    public Soup.Message msg;
+    public Soup.Status expected_code;
+
+    public TestRequestFactory (Soup.Message msg,
+                               Soup.Status expected_code) {
+        this.msg = msg;
+        this.expected_code = expected_code;
+    }
+
+    internal HTTPGet create_get (HTTPServer http_server,
+                                 Soup.Server server,
+                                 Soup.Message msg) {
+        HTTPGet request = new HTTPGet (http_server, server, msg);
+        request.handler = null;
+
+        return request;
+    }
+}
+
 public class Rygel.HTTPGetTest : GLib.Object {
     protected HTTPServer server;
     protected HTTPClient client;
@@ -54,6 +82,9 @@ public class Rygel.HTTPGetTest : GLib.Object {
 
     private Error error;
 
+    private ArrayList<TestRequestFactory> requests;
+    private TestRequestFactory current_request;
+
     public static int main (string[] args) {
         try {
             var test = new HTTPGetTest ();
@@ -67,14 +98,19 @@ public class Rygel.HTTPGetTest : GLib.Object {
             return -1;
         }
 
+        /* Avoid some warnings about unused methods: */
+        var item = new VideoItem();
+        assert (!item.is_live_stream());
+        assert (!item.streamable());
+
         return 0;
     }
 
     public HTTPGetTest () throws Error {
         this.server = new HTTPServer ();
-        this.client = new HTTPClient (this.server.context,
-                                      this.server.uri);
+        this.client = new HTTPClient (this.server.context);
         this.main_loop = new MainLoop (null, false);
+        this.create_test_messages();
     }
 
     public virtual void run () throws Error {
@@ -82,7 +118,7 @@ public class Rygel.HTTPGetTest : GLib.Object {
         this.server.message_received.connect (this.on_message_received);
         this.client.completed.connect (this.on_client_completed);
 
-        this.client.run.begin ();
+        this.start_next_test_request ();
 
         this.main_loop.run ();
 
@@ -91,18 +127,92 @@ public class Rygel.HTTPGetTest : GLib.Object {
         }
     }
 
-    private HTTPRequest create_request (Soup.Message msg) throws Error {
-        return new HTTPGet (this.server,
-                            this.server.context.server,
-                            msg);
+    private void create_test_messages () {
+        requests = new ArrayList<TestRequestFactory> ();
+
+        Soup.Message request = new Soup.Message ("POST", this.server.uri);
+        requests.add (new TestRequestFactory (request,
+                      Soup.Status.BAD_REQUEST));
+
+        request = new Soup.Message ("HEAD", this.server.uri);
+        requests.add (new TestRequestFactory (request, Soup.Status.OK));
+
+        request = new Soup.Message ("GET", this.server.uri);
+        requests.add (new TestRequestFactory (request, Soup.Status.OK));
+
+        string uri = this.server.create_uri ("VideoItem");
+        uri = uri + "/tr/MP3";
+        request = new Soup.Message ("HEAD", uri);
+        requests.add (new TestRequestFactory (request, Soup.Status.OK));
+
+        request = new Soup.Message ("GET", this.server.uri);
+        request.request_headers.append ("transferMode.dlna.org", "Streaming");
+        requests.add (new TestRequestFactory (request, Soup.Status.OK));
+
+        request = new Soup.Message ("GET", this.server.uri);
+        request.request_headers.append ("transferMode.dlna.org", "Interactive");
+        requests.add (new TestRequestFactory (request,
+                      Soup.Status.NOT_ACCEPTABLE));
+
+        request = new Soup.Message ("GET", this.server.uri);
+        request.request_headers.append ("Range", "bytes=1-2");
+        requests.add (new TestRequestFactory (request,
+                      Soup.Status.OK));
+
+        uri = this.server.create_uri ("AudioItem");
+        uri = uri + "/th/0";
+
+        request = new Soup.Message ("GET", uri);
+        requests.add (new TestRequestFactory (request,
+                      Soup.Status.NOT_FOUND));
+
+        request = new Soup.Message ("GET", this.server.uri);
+        request.request_headers.append ("TimeSeekRange.dlna.org", "0");
+        requests.add (new TestRequestFactory (request,
+                      Soup.Status.NOT_ACCEPTABLE));
+
+        uri = this.server.create_uri ("AudioItem");
+        request = new Soup.Message ("GET", uri);
+        request.request_headers.append ("TimeSeekRange.dlna.org", "0");
+        requests.add (new TestRequestFactory (request,
+                      Soup.Status.BAD_REQUEST));
+
+        uri = this.server.create_uri ("AudioItem");
+        request = new Soup.Message ("GET", uri);
+        request.request_headers.append ("TimeSeekRange.dlna.org", "npt=1-2049");
+        requests.add (new TestRequestFactory (request,
+                      Soup.Status.REQUESTED_RANGE_NOT_SATISFIABLE));
+
+        request = new Soup.Message ("GET", this.server.uri);
+        request.request_headers.append ("clienthacks.test.rygel", "f");
+        requests.add (new TestRequestFactory (request,
+                      Soup.Status.OK));
+
+        request = new Soup.Message ("GET", this.server.uri);
+        request.request_headers.append ("clienthacks.test.rygel", "t");
+        requests.add (new TestRequestFactory (request,
+                      Soup.Status.OK));
+    }
+
+    private HTTPGet create_request (Soup.Message msg) throws Error {
+        HTTPGet request = this.current_request.create_get (this.server,
+                            this.server.context.server, msg);
+        return request;
     }
 
     private void on_client_completed (StateMachine client) {
-        if (this.server_done) {
+        if (requests.size > 0) {
+            this.start_next_test_request ();
+        } else {
             this.main_loop.quit ();
+            this.client_done = true;
         }
+    }
 
-        this.client_done = true;
+    private void start_next_test_request() {
+        this.current_request = requests.remove_at (0);
+        this.client.msg = this.current_request.msg;
+        this.client.run.begin ();
     }
 
     private void on_message_received (HTTPServer   server,
@@ -116,7 +226,10 @@ public class Rygel.HTTPGetTest : GLib.Object {
 
             yield request.run ();
 
-            assert ((request as HTTPGet).item != null);
+            assert ((request as HTTPGet).object != null);
+
+            debug ("status.code: %d", (int) msg.status_code);
+            assert (msg.status_code == this.current_request.expected_code);
 
             if (this.client_done) {
                 this.main_loop.quit ();
@@ -152,13 +265,19 @@ public class Rygel.HTTPServer : GLib.Object {
 
     public string uri {
         owned get {
-            var item_uri = new HTTPItemURI (this.root_container.ITEM_ID,
-                                            this);
-
-            return item_uri.to_string ();
+            return create_uri("VideoItem");
         }
     }
 
+    public string create_uri (string item_id) {
+        var item = new VideoItem ();
+        item.id = item_id;
+
+        var item_uri = new HTTPItemURI (item, this);
+
+        return item_uri.to_string ();
+    }
+
     public signal void message_received (Soup.Message message);
 
     public HTTPServer () throws TestError {
@@ -187,7 +306,12 @@ public class Rygel.HTTPServer : GLib.Object {
     }
 
     public Transcoder get_transcoder (string target) throws Error {
-        return new Transcoder ();
+        if (target == "MP3") {
+            return new Transcoder ("mp3");
+        }
+        throw new HTTPRequestError.NOT_FOUND (
+                            "No transcoder available for target format '%s'",
+                            target);
     }
 }
 
@@ -197,12 +321,8 @@ public class Rygel.HTTPClient : GLib.Object, StateMachine {
 
     public Cancellable cancellable { get; set; }
 
-    public HTTPClient (GUPnP.Context context,
-                       string        uri) {
+    public HTTPClient (GUPnP.Context context) {
         this.context = context;
-
-        this.msg = new Soup.Message ("GET",  uri);
-        assert (this.msg != null);
     }
 
     public async void run () {
@@ -219,7 +339,6 @@ public class Rygel.HTTPClient : GLib.Object, StateMachine {
 }
 
 public class Rygel.MediaContainer : Rygel.MediaObject {
-    public const string ITEM_ID = "TestItem";
 
     public async MediaObject? find_object (string       item_id,
                                            Cancellable? cancellable)
@@ -233,8 +352,11 @@ public class Rygel.MediaContainer : Rygel.MediaObject {
 
         yield;
 
-        if (item_id == ITEM_ID) {
+        debug ("item id: %s", item_id);
+        if (item_id == "VideoItem") {
             return new VideoItem ();
+        } else if (item_id == "AudioItem") {
+            return new AudioItem ();
         } else {
             return null;
         }
@@ -247,6 +369,8 @@ internal abstract class Rygel.HTTPGetHandler {
     }
 
     public void add_response_headers (HTTPGet get_request) {}
+
+    public bool knows_size (HTTPGet request) { return false; }
 }
 
 internal class Rygel.HTTPTranscodeHandler : Rygel.HTTPGetHandler {
@@ -258,15 +382,23 @@ internal class Rygel.HTTPIdentityHandler : Rygel.HTTPGetHandler {
     public HTTPIdentityHandler (Cancellable cancellable) {}
 }
 
+internal class Rygel.HTTPPlaylistHandler : Rygel.HTTPGetHandler {
+    public HTTPPlaylistHandler (string? arg, Cancellable cancellable) {}
+
+    public static bool is_supported (string? arg) { return true; }
+}
+
 public abstract class Rygel.MediaItem : Rygel.MediaObject {
     public long size = 1024;
-    public ArrayList<Subtitle> subtitles = new ArrayList<Subtitle> ();
-    public ArrayList<Thumbnail> thumbnails = new ArrayList<Thumbnail> ();
+    public ArrayList<string> uris = new ArrayList<string> ();
 
     public bool place_holder = false;
 
     public bool is_live_stream () {
-        return true;
+        if (this.id == "VideoItem")
+            return false;
+        else
+            return true;
     }
 
     public bool streamable () {
@@ -276,27 +408,50 @@ public abstract class Rygel.MediaItem : Rygel.MediaObject {
 
 private class Rygel.AudioItem : MediaItem {
     public int64 duration = 2048;
+
+    public AudioItem () {
+        this.id = "AudioItem";
+    }
 }
 
 private interface Rygel.VisualItem : MediaItem {
     public abstract int width { get; set; }
     public abstract int height { get; set; }
-    public abstract int pixel_width { get; set; }
-    public abstract int pixel_height { get; set; }
     public abstract int color_depth { get; set; }
 
     public abstract ArrayList<Thumbnail> thumbnails { get; protected set; }
+
+    public bool is_live_stream () {
+        return false;
+    }
+
+    public bool streamable () {
+        return false;
+    }
 }
 
 private class Rygel.VideoItem : AudioItem, VisualItem {
     public int width { get; set; default = -1; }
     public int height { get; set; default = -1; }
-    public int pixel_width { get; set; default = -1; }
-    public int pixel_height { get; set; default = -1; }
     public int color_depth { get; set; default = -1; }
 
-    public ArrayList<Thumbnail> thumbnails { get; protected set; }
-    public ArrayList<Subtitle> subtitles;
+    private ArrayList<Thumbnail> ts;
+
+    public VideoItem () {
+        this.id = "VideoItem";
+    }
+
+    public ArrayList<Thumbnail> thumbnails {
+        get {
+            this.ts = new ArrayList<Thumbnail>();
+            ts.add(new Rygel.Thumbnail());
+            return this.ts;
+        }
+
+        protected set {}
+    }
+
+    public ArrayList<Subtitle> subtitles = new ArrayList<Subtitle> ();
 }
 
 private class Rygel.MusicItem : AudioItem {
@@ -305,10 +460,12 @@ private class Rygel.MusicItem : AudioItem {
 
 public class Rygel.Thumbnail {
     public long size = 1024;
+    public string file_extension;
 }
 
 public class Rygel.Subtitle {
     public long size = 1024;
+    public string caption_type;
 }
 
 internal class Rygel.HTTPResponse : Rygel.StateMachine, GLib.Object {
@@ -319,6 +476,7 @@ internal class Rygel.HTTPResponse : Rygel.StateMachine, GLib.Object {
 
     public HTTPResponse (HTTPGet get_request) {
         this.msg = get_request.msg;
+        this.msg.response_headers.set_encoding (Soup.Encoding.CONTENT_LENGTH);
         this.server = get_request.server;
     }
 
@@ -333,7 +491,7 @@ internal class Rygel.HTTPResponse : Rygel.StateMachine, GLib.Object {
 
         yield;
 
-        this.msg.set_status (Soup.KnownStatusCode.OK);
+        this.msg.set_status (Soup.Status.OK);
         this.server.unpause_message (msg);
 
         this.completed ();
@@ -342,6 +500,13 @@ internal class Rygel.HTTPResponse : Rygel.StateMachine, GLib.Object {
 
 public class Rygel.MediaObject {
     public string id;
+    public string mime_type = "";
 }
 
-public class Rygel.Transcoder {}
+public class Rygel.Transcoder : GLib.Object {
+    public string extension { get; protected set; }
+
+    public Transcoder (string extension) {
+        this.extension = extension;
+    }
+}