TIMEOUT
}
+public errordomain Rygel.ClientHacksError {
+ NA
+}
+
+public class Rygel.ClientHacks {
+ public static ClientHacks create (Message? message) throws Error {
+ throw new ClientHacksError.NA ("");
+ }
+
+ public void apply (MediaItem item) {
+ }
+}
+
+public class Rygel.TestRequestFactory {
+ public Soup.Message msg;
+ public Soup.Status? expected_code;
+ public bool cancel;
+
+ public TestRequestFactory (Soup.Message msg,
+ Soup.Status? expected_code,
+ bool cancel = false) {
+ this.msg = msg;
+ this.expected_code = expected_code;
+ this.cancel = cancel;
+ }
+
+ internal HTTPPost create_post (HTTPServer http_server,
+ Soup.Server server,
+ Soup.Message msg) {
+ HTTPPost request = new HTTPPost (http_server, server, msg);
+
+ return request;
+ }
+}
+
public class Rygel.HTTPPostTest : GLib.Object {
protected HTTPServer server;
protected HTTPClient client;
-
private bool server_done;
private bool client_done;
+ private bool ready;
private MainLoop main_loop;
-
private Error error;
+ private ArrayList<TestRequestFactory> requests;
+ private TestRequestFactory current_request;
+
public static int main (string[] args) {
try {
var test = new HTTPPostTest ();
public HTTPPostTest () 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 {
+ // cleanup
+ var file = File.new_for_uri (MediaItem.URI);
+ FileUtils.remove (file.get_path ());
+
Timeout.add_seconds (3, this.on_timeout);
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 ();
}
}
+ private void create_test_messages () {
+ requests = new ArrayList<TestRequestFactory> ();
+
+ var request = new Soup.Message ("POST", this.server.uri);
+ requests.add (new TestRequestFactory (request, Soup.Status.OK));
+
+ request = new Soup.Message ("POST", this.server.uri);
+ requests.add (new TestRequestFactory (request,
+ Soup.Status.NOT_FOUND));
+
+ request = new Soup.Message ("POST", this.server.create_uri ("NullItem"));
+ requests.add (new TestRequestFactory (request,
+ Soup.Status.BAD_REQUEST));
+
+ request = new Soup.Message ("POST",
+ this.server.create_uri ("ErrorItem"));
+ requests.add (new TestRequestFactory (request,
+ Soup.Status.OK));
+
+ request = new Soup.Message ("POST",
+ this.server.create_uri ("CancelItem"));
+ requests.add (new TestRequestFactory (request,
+ Soup.Status.OK, true));
+
+ request = new Soup.Message ("POST",
+ this.server.create_uri ("VanishingItem"));
+ requests.add (new TestRequestFactory (request, Soup.Status.OK));
+ }
+
private HTTPRequest create_request (Soup.Message msg) throws Error {
- return new HTTPPost (this.server,
- this.server.context.server,
- msg);
+ var srv = this.server.context.server;
+ var request = this.current_request.create_post (this.server, srv, msg);
+
+ return request;
+ }
+
+ 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_client_completed (StateMachine client) {
- this.client_done = true;
- this.check_and_exit.begin ();
+ if (requests.size > 0) {
+ if (this.server_done) {
+ this.server_done = false;
+ this.start_next_test_request ();
+ } else {
+ this.ready = true;
+ }
+ } else {
+ if (this.server_done) {
+ this.main_loop.quit ();
+ }
+ this.client_done = true;
+ }
}
private void on_message_received (HTTPServer server,
try {
var request = this.create_request (msg);
- yield request.run ();
+ if (this.current_request.cancel) {
+ request.cancellable.cancel ();
+ } else {
+ yield request.run ();
+
+ debug ("status.code: %d", (int) msg.status_code);
+ assert (msg.status_code == this.current_request.expected_code);
+
+ this.check_result.begin ();
+ }
- assert ((request as HTTPPost).item != null);
+ if (this.client_done) {
+ this.main_loop.quit ();
+ } else if (this.ready) {
+ this.ready = false;
- this.server_done = true;
- this.check_and_exit.begin ();
+ start_next_test_request ();
+ } else {
+ this.server_done = true;
+ }
} catch (Error error) {
this.error = error;
this.main_loop.quit ();
return false;
}
- private async void check_and_exit () {
- if (!(this.server_done && this.client_done)) {
- return;
- }
-
+ private async void check_result () {
try {
var file = this.server.root_container.item.file;
var stream = yield file.read_async (Priority.HIGH, null);
- var buffer = new char[HTTPClient.LENGTH];
+ var buffer = new uint8[HTTPClient.LENGTH];
+ yield stream.read_async (buffer, Priority.HIGH, null);
- yield stream.read_async (buffer,
- HTTPClient.LENGTH,
- Priority.HIGH,
- null);
for (var i = 0; i < HTTPClient.LENGTH; i++) {
assert (buffer[i] == this.client.content[i]);
}
+ } catch (IOError.NOT_FOUND e) {
+ return;
} catch (Error error) {
this.error = error;
- }
- this.main_loop.quit ();
+ this.main_loop.quit ();
+ }
}
}
public string uri {
owned get {
- var item_uri = new HTTPItemURI (this.root_container.ITEM_ID,
- this);
-
+ var item = new MediaItem (MediaContainer.ITEM_ID, this.root_container);
+ var item_uri = new HTTPItemURI (item, this);
return item_uri.to_string ();
}
}
+ public string create_uri(string item_id) {
+ var item = new MediaItem (item_id, this.root_container);
+ var item_uri = new HTTPItemURI (item, this);
+ return item_uri.to_string ();
+ }
+
public signal void message_received (Soup.Message message);
public HTTPServer () throws TestError {
private void on_got_headers (Soup.Message msg) {
this.message_received (msg);
}
+
+ public Transcoder get_transcoder (string target) throws Error {
+ if (target == "MP3") {
+ return new Transcoder ("mp3");
+ }
+ throw new HTTPRequestError.NOT_FOUND (
+ "No transcoder available for target format '%s'",
+ target);
+ }
}
public class Rygel.HTTPClient : GLib.Object, StateMachine {
public const size_t LENGTH = 1024;
- public char[] content;
+ public uint8[] content;
public GUPnP.Context context;
public Soup.Message msg;
public Cancellable cancellable { get; set; }
- public HTTPClient (GUPnP.Context context,
- string uri) {
+ public HTTPClient (GUPnP.Context context) {
this.context = context;
- this.content = new char[1024];
-
- this.msg = new Soup.Message ("POST", uri);
- assert (this.msg != null);
+ this.content = new uint8[1024];
}
public async void run () {
SourceFunc run_continue = run.callback;
- this.msg.request_body.append (MemoryUse.COPY, content, LENGTH);
+ this.msg.request_body.append (MemoryUse.COPY, content);
this.context.session.queue_message (this.msg, (session, msg) => {
run_continue ();
public class Rygel.MediaContainer : Rygel.MediaObject {
public const string ITEM_ID = "TestItem";
+ public signal void container_updated (MediaContainer container);
+
public MediaItem item;
+ private bool vanish;
+ private bool error;
+
+ public File file;
+ private FileMonitor monitor;
public MediaContainer () {
- this.item = new MediaItem (ITEM_ID);
+ this.file = File.new_for_uri (MediaItem.URI);
+ this.item = new MediaItem (ITEM_ID, this);
+ this.vanish = false;
+ this.error = false;
+ this.id = "TesContainer";
+
+ try {
+ this.monitor = this.file.monitor_file (FileMonitorFlags.NONE);
+ } catch (GLib.Error error) {
+ assert_not_reached ();
+ }
+
+ this.monitor.changed.connect (this.on_file_changed);
}
public async MediaObject? find_object (string item_id,
yield;
- if (item_id == ITEM_ID) {
- return this.item;
- } else {
+ if (item_id == "ErrorItem" && this.error) {
+ var msg = _("Fake error caused by %s object.");
+ this.file.delete (null);
+
+ throw new ContentDirectoryError.INVALID_ARGS (msg, item_id);
+ } else if (item_id == "ErrorItem" && !this.error) {
+ this.error = true;
+ }
+
+ if (item_id == "VanishingItem" && this.vanish) {
+ this.file.delete (null);
+
return null;
+ } else if (item_id == "VanishingItem" && !this.vanish) {
+ this.vanish = true;
+ }
+
+ if (item_id != this.item.id) {
+ this.item = new MediaItem (item_id, this);
+ }
+
+ return this.item;
+ }
+
+ public void on_file_changed (FileMonitor monitor,
+ File file,
+ File? other_file,
+ FileMonitorEvent event_type) {
+ this.item.place_holder = false;
+
+ this.container_updated (this);
+ }
+
+ ~MediaContainer() {
+ try {
+ this.file.delete (null);
+ } catch (GLib.Error error) {
+ assert_not_reached ();
}
}
}
public class Rygel.MediaItem : Rygel.MediaObject {
public const string URI = "file:///tmp/rygel-upload-test.wav";
- public string id;
public long size = 1024;
public long duration = 1024;
+ public ArrayList<string> uris = new ArrayList<string> ();
+
+ public bool place_holder = true;
public File file;
- public MediaItem (string id) {
+ public MediaItem.for_visual_item () {}
+
+ public MediaItem (string id, MediaContainer parent) {
this.id = id;
+ this.parent = parent;
- this.file = File.new_for_uri (URI);
- try {
- this.file.replace (null, false, 0, null);
- } catch (IOError.EXISTS error) {
- } catch (GLib.Error error) {
- assert_not_reached ();
- }
- }
-
- ~MediaItem() {
- try {
- this.file.delete (null);
- } catch (GLib.Error error) {
- assert_not_reached ();
- }
+ this.file = parent.file;
}
public async File? get_writable (Cancellable? cancellable) throws Error {
yield;
- return this.file;
+ if (this.id == "NullItem") {
+ this.file.delete (null);
+
+ return null;
+ } else {
+ return this.file;
+ }
}
}
public HTTPResponse (HTTPPost get_request) {
this.msg = get_request.msg;
+
this.server = get_request.server;
}
yield;
- this.msg.set_status (Soup.KnownStatusCode.OK);
+ this.msg.set_status (Soup.Status.OK);
this.server.unpause_message (msg);
this.completed ();
}
}
-public class Rygel.MediaObject {}
+public class Rygel.ObjectRemovalQueue: GLib.Object {
+ public static ObjectRemovalQueue get_default () {
+ return new ObjectRemovalQueue ();
+ }
+
+ public bool dequeue (MediaObject item) {
+ return true;
+ }
+
+ public async void remove_now (MediaObject item, Cancellable? cancellable) {
+ Idle.add (remove_now.callback);
+
+ yield;
+ }
+}
+
+public class Rygel.MediaObject : GLib.Object {
+ public string id;
+ public unowned MediaContainer parent;
+ public string mime_type = "";
+}
+
+public class Rygel.Thumbnail : GLib.Object {
+ public string file_extension;
+}
+
+public class Rygel.VisualItem : Rygel.MediaItem {
+ public ArrayList<Thumbnail> thumbnails = new ArrayList<Thumbnail> ();
+
+ public VisualItem () {
+ base.for_visual_item();
+ }
+}
+
+private class Rygel.Subtitle : GLib.Object {
+ public string caption_type;
+}
+
+private class Rygel.VideoItem : Rygel.VisualItem {
+ public ArrayList<Subtitle> subtitles = new ArrayList<Subtitle> ();
+}
+
+private class Rygel.MusicItem : MediaItem {
+ public Thumbnail album_art;
+
+ public MusicItem (string id, MediaContainer parent) {
+ base (id, parent);
+ }
+}
+
+public errordomain Rygel.ContentDirectoryError {
+ INVALID_ARGS = 402
+}
+
+public class Rygel.Transcoder : GLib.Object {
+ public string extension { get; protected set; }
+
+ public Transcoder (string extension) {
+ this.extension = extension;
+ }
+}