/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * GData Client * Copyright (C) Philip Withnall 2008–2010, 2015 * * GData Client is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * GData Client is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with GData Client. If not, see . */ #include #include #include #include "gdata.h" #include "common.h" #include "gdata-dummy-authorizer.h" static UhmServer *mock_server = NULL; #undef CLIENT_ID /* from common.h */ #define DEVELOPER_KEY "AI39si7Me3Q7zYs6hmkFvpRBD2nrkVjYYsUO5lh_3HdOkGRc9g6Z4nzxZatk_aAo2EsA21k7vrda0OO6oFg2rnhMedZXPyXoEw" #define CLIENT_ID "352818697630-nqu2cmt5quqd6lr17ouoqmb684u84l1f.apps.googleusercontent.com" #define CLIENT_SECRET "-fA4pHQJxR3zJ-FyAMPQsikg" #define REDIRECT_URI "urn:ietf:wg:oauth:2.0:oob" /* Effectively gdata_test_mock_server_start_trace() but calling uhm_server_run() instead of uhm_server_start_trace(). */ static void gdata_test_mock_server_run (UhmServer *server) { const gchar *ip_address; UhmResolver *resolver; uhm_server_run (server); gdata_test_set_https_port (server); if (uhm_server_get_enable_online (server) == FALSE) { /* Set up the expected domain names here. This should technically be split up between * the different unit test suites, but that's too much effort. */ ip_address = uhm_server_get_address (server); resolver = uhm_server_get_resolver (server); uhm_resolver_add_A (resolver, "www.google.com", ip_address); uhm_resolver_add_A (resolver, "gdata.youtube.com", ip_address); uhm_resolver_add_A (resolver, "uploads.gdata.youtube.com", ip_address); } } static void test_authentication (void) { GDataOAuth2Authorizer *authorizer = NULL; /* owned */ gchar *authentication_uri, *authorisation_code; gdata_test_mock_server_start_trace (mock_server, "authentication"); authorizer = gdata_oauth2_authorizer_new (CLIENT_ID, CLIENT_SECRET, REDIRECT_URI, GDATA_TYPE_YOUTUBE_SERVICE); /* Get an authentication URI. */ authentication_uri = gdata_oauth2_authorizer_build_authentication_uri (authorizer, NULL, FALSE); g_assert (authentication_uri != NULL); /* Get the authorisation code off the user. */ if (uhm_server_get_enable_online (mock_server)) { authorisation_code = gdata_test_query_user_for_verifier (authentication_uri); } else { /* Hard coded, extracted from the trace file. */ authorisation_code = g_strdup ("4/9qV_LanNEOUOL4sftMwUp4cfa_yeF" "assB6-ys5EkA5o.4rgOzrZMXgcboiIB" "eO6P2m-GWLMXmgI"); } g_free (authentication_uri); if (authorisation_code == NULL) { /* Skip tests. */ goto skip_test; } /* Authorise the token */ g_assert (gdata_oauth2_authorizer_request_authorization (authorizer, authorisation_code, NULL, NULL) == TRUE); /* Check all is as it should be */ g_assert (gdata_authorizer_is_authorized_for_domain (GDATA_AUTHORIZER (authorizer), gdata_youtube_service_get_primary_authorization_domain ()) == TRUE); skip_test: g_free (authorisation_code); g_object_unref (authorizer); uhm_server_end_trace (mock_server); } static void test_service_properties (void) { GDataService *service; /* Create a service */ service = GDATA_SERVICE (gdata_youtube_service_new (DEVELOPER_KEY, NULL)); g_assert (service != NULL); g_assert (GDATA_IS_SERVICE (service)); g_assert_cmpstr (gdata_youtube_service_get_developer_key (GDATA_YOUTUBE_SERVICE (service)), ==, DEVELOPER_KEY); g_object_unref (service); } static void test_query_standard_feeds (gconstpointer service) { GDataFeed *feed; GError *error = NULL; guint i; gulong filter_id; GDataYouTubeStandardFeedType feeds[] = { /* This must be kept up-to-date with GDataYouTubeStandardFeedType. */ GDATA_YOUTUBE_TOP_RATED_FEED, GDATA_YOUTUBE_TOP_FAVORITES_FEED, GDATA_YOUTUBE_MOST_VIEWED_FEED, GDATA_YOUTUBE_MOST_POPULAR_FEED, GDATA_YOUTUBE_MOST_RECENT_FEED, GDATA_YOUTUBE_MOST_DISCUSSED_FEED, GDATA_YOUTUBE_MOST_LINKED_FEED, GDATA_YOUTUBE_MOST_RESPONDED_FEED, GDATA_YOUTUBE_RECENTLY_FEATURED_FEED, GDATA_YOUTUBE_WATCH_ON_MOBILE_FEED, }; const gchar *ignore_query_param_values[] = { "publishedAfter", NULL, }; filter_id = uhm_server_filter_ignore_parameter_values (mock_server, ignore_query_param_values); gdata_test_mock_server_start_trace (mock_server, "query-standard-feeds"); for (i = 0; i < G_N_ELEMENTS (feeds); i++) { feed = gdata_youtube_service_query_standard_feed (GDATA_YOUTUBE_SERVICE (service), feeds[i], NULL, NULL, NULL, NULL, &error); g_assert_no_error (error); g_assert (GDATA_IS_FEED (feed)); g_clear_error (&error); g_assert_cmpuint (g_list_length (gdata_feed_get_entries (feed)), >, 0); g_object_unref (feed); } uhm_server_end_trace (mock_server); uhm_server_compare_messages_remove_filter (mock_server, filter_id); } static void test_query_standard_feed (gconstpointer service) { GDataFeed *feed; GError *error = NULL; gulong filter_id; const gchar *ignore_query_param_values[] = { "publishedAfter", NULL, }; filter_id = uhm_server_filter_ignore_parameter_values (mock_server, ignore_query_param_values); gdata_test_mock_server_start_trace (mock_server, "query-standard-feed"); feed = gdata_youtube_service_query_standard_feed (GDATA_YOUTUBE_SERVICE (service), GDATA_YOUTUBE_TOP_RATED_FEED, NULL, NULL, NULL, NULL, &error); g_assert_no_error (error); g_assert (GDATA_IS_FEED (feed)); g_clear_error (&error); g_assert_cmpuint (g_list_length (gdata_feed_get_entries (feed)), >, 0); g_object_unref (feed); uhm_server_end_trace (mock_server); uhm_server_compare_messages_remove_filter (mock_server, filter_id); } static void test_query_standard_feed_with_query (gconstpointer service) { GDataYouTubeQuery *query; GDataFeed *feed; GError *error = NULL; gulong filter_id; const gchar *ignore_query_param_values[] = { "publishedAfter", NULL, }; filter_id = uhm_server_filter_ignore_parameter_values (mock_server, ignore_query_param_values); G_GNUC_BEGIN_IGNORE_DEPRECATIONS gdata_test_mock_server_start_trace (mock_server, "query-standard-feed-with-query"); query = gdata_youtube_query_new (NULL); gdata_youtube_query_set_language (query, "fr"); feed = gdata_youtube_service_query_standard_feed (GDATA_YOUTUBE_SERVICE (service), GDATA_YOUTUBE_TOP_RATED_FEED, GDATA_QUERY (query), NULL, NULL, NULL, &error); g_assert_no_error (error); g_assert (GDATA_IS_FEED (feed)); g_clear_error (&error); g_assert_cmpuint (g_list_length (gdata_feed_get_entries (feed)), >, 0); g_object_unref (query); g_object_unref (feed); uhm_server_end_trace (mock_server); uhm_server_compare_messages_remove_filter (mock_server, filter_id); G_GNUC_END_IGNORE_DEPRECATIONS } /* HTTP message responses and the expected associated GData error domain/code. */ static const GDataTestRequestErrorData query_standard_feed_errors[] = { /* Generic network errors. */ { SOUP_STATUS_BAD_REQUEST, "Bad Request", "Invalid parameter ‘foobar’.", gdata_service_error_quark, GDATA_SERVICE_ERROR_PROTOCOL_ERROR }, { SOUP_STATUS_NOT_FOUND, "Not Found", "Login page wasn't found for no good reason at all.", gdata_service_error_quark, GDATA_SERVICE_ERROR_NOT_FOUND }, { SOUP_STATUS_PRECONDITION_FAILED, "Precondition Failed", "Not allowed to log in at this time, possibly.", gdata_service_error_quark, GDATA_SERVICE_ERROR_CONFLICT }, { SOUP_STATUS_INTERNAL_SERVER_ERROR, "Internal Server Error", "Whoops.", gdata_service_error_quark, GDATA_SERVICE_ERROR_PROTOCOL_ERROR }, #if 0 FIXME /* Specific query errors. */ { SOUP_STATUS_FORBIDDEN, "Too Many Calls", "yt:quotatoo_many_recent_calls", gdata_youtube_service_error_quark, GDATA_YOUTUBE_SERVICE_ERROR_API_QUOTA_EXCEEDED }, { SOUP_STATUS_FORBIDDEN, "Too Many Entries", "yt:quotatoo_many_entries", gdata_youtube_service_error_quark, GDATA_YOUTUBE_SERVICE_ERROR_ENTRY_QUOTA_EXCEEDED }, { SOUP_STATUS_SERVICE_UNAVAILABLE, "Maintenance", "yt:servicedisabled_in_maintenance_mode", gdata_service_error_quark, GDATA_SERVICE_ERROR_UNAVAILABLE }, { SOUP_STATUS_FORBIDDEN, "YouTube Signup Required", "yt:serviceyoutube_signup_required", gdata_youtube_service_error_quark, GDATA_YOUTUBE_SERVICE_ERROR_CHANNEL_REQUIRED }, { SOUP_STATUS_FORBIDDEN, "Forbidden", "yt:authenticationTokenExpired" "Authorization: GoogleLogin", gdata_service_error_quark, GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED }, /* Malformed YouTube errors to test parser error handling. */ { SOUP_STATUS_INTERNAL_SERVER_ERROR, "Malformed XML", "", gdata_service_error_quark, GDATA_SERVICE_ERROR_PROTOCOL_ERROR }, { SOUP_STATUS_FORBIDDEN, "Empty Response", "", gdata_service_error_quark, GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED }, { SOUP_STATUS_INTERNAL_SERVER_ERROR, "Unknown Element", " ", gdata_service_error_quark, GDATA_SERVICE_ERROR_PROTOCOL_ERROR }, { SOUP_STATUS_INTERNAL_SERVER_ERROR, "Wrong Top-Level Element", "", gdata_service_error_quark, GDATA_SERVICE_ERROR_PROTOCOL_ERROR }, { SOUP_STATUS_FORBIDDEN, "Unknown Error Code (Service)", "yt:serviceUnknownCode", gdata_service_error_quark, GDATA_SERVICE_ERROR_PROTOCOL_ERROR }, { SOUP_STATUS_FORBIDDEN, "Unknown Error Code (Quota)", "yt:quotaUnknownCode", gdata_service_error_quark, GDATA_SERVICE_ERROR_PROTOCOL_ERROR }, { SOUP_STATUS_FORBIDDEN, "Unknown Error Domain", "yt:foobazTokenExpired", gdata_service_error_quark, GDATA_SERVICE_ERROR_PROTOCOL_ERROR }, #endif }; static void test_query_standard_feed_error (gconstpointer service) { GDataFeed *feed; GError *error = NULL; gulong handler_id, filter_id; guint i; const gchar *ignore_query_param_values[] = { "publishedAfter", NULL, }; if (uhm_server_get_enable_logging (mock_server) == TRUE) { g_test_message ("Ignoring test due to logging being enabled."); return; } else if (uhm_server_get_enable_online (mock_server) == TRUE) { g_test_message ("Ignoring test due to running online and test not being reproducible."); return; } filter_id = uhm_server_filter_ignore_parameter_values (mock_server, ignore_query_param_values); for (i = 0; i < G_N_ELEMENTS (query_standard_feed_errors); i++) { const GDataTestRequestErrorData *data = &query_standard_feed_errors[i]; handler_id = g_signal_connect (mock_server, "handle-message", (GCallback) gdata_test_mock_server_handle_message_error, (gpointer) data); gdata_test_mock_server_run (mock_server); /* Query the feed. */ feed = gdata_youtube_service_query_standard_feed (GDATA_YOUTUBE_SERVICE (service), GDATA_YOUTUBE_TOP_RATED_FEED, NULL, NULL, NULL, NULL, &error); g_assert_error (error, data->error_domain_func (), data->error_code); g_assert (feed == NULL); g_clear_error (&error); uhm_server_stop (mock_server); g_signal_handler_disconnect (mock_server, handler_id); } uhm_server_compare_messages_remove_filter (mock_server, filter_id); } static void test_query_standard_feed_timeout (gconstpointer service) { GDataFeed *feed; GError *error = NULL; gulong handler_id, filter_id; const gchar *ignore_query_param_values[] = { "publishedAfter", NULL, }; if (uhm_server_get_enable_logging (mock_server) == TRUE) { g_test_message ("Ignoring test due to logging being enabled."); return; } else if (uhm_server_get_enable_online (mock_server) == TRUE) { g_test_message ("Ignoring test due to running online and test not being reproducible."); return; } filter_id = uhm_server_filter_ignore_parameter_values (mock_server, ignore_query_param_values); handler_id = g_signal_connect (mock_server, "handle-message", (GCallback) gdata_test_mock_server_handle_message_timeout, NULL); gdata_test_mock_server_run (mock_server); /* Set the service's timeout as low as possible (1 second). */ gdata_service_set_timeout (GDATA_SERVICE (service), 1); /* Query the feed. */ feed = gdata_youtube_service_query_standard_feed (GDATA_YOUTUBE_SERVICE (service), GDATA_YOUTUBE_TOP_RATED_FEED, NULL, NULL, NULL, NULL, &error); g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_NETWORK_ERROR); g_assert (feed == NULL); g_clear_error (&error); uhm_server_stop (mock_server); g_signal_handler_disconnect (mock_server, handler_id); uhm_server_compare_messages_remove_filter (mock_server, filter_id); } typedef struct { GDataAsyncTestData async_data; gulong filter_id; } StandardFeedData; static void set_up_standard_feed_async (StandardFeedData *standard_feed_data, gconstpointer test_data) { const gchar *ignore_query_param_values[] = { "publishedAfter", NULL, }; gdata_set_up_async_test_data (&standard_feed_data->async_data, test_data); standard_feed_data->filter_id = uhm_server_filter_ignore_parameter_values (mock_server, ignore_query_param_values); } static void tear_down_standard_feed_async (StandardFeedData *standard_feed_data, gconstpointer test_data) { uhm_server_compare_messages_remove_filter (mock_server, standard_feed_data->filter_id); gdata_tear_down_async_test_data (&standard_feed_data->async_data, test_data); } GDATA_ASYNC_TEST_FUNCTIONS (query_standard_feed, void, G_STMT_START { gdata_youtube_service_query_standard_feed_async (GDATA_YOUTUBE_SERVICE (service), GDATA_YOUTUBE_TOP_RATED_FEED, NULL, cancellable, NULL, NULL, NULL, async_ready_callback, async_data); } G_STMT_END, G_STMT_START { GDataFeed *feed; feed = gdata_service_query_finish (GDATA_SERVICE (obj), async_result, &error); if (error == NULL) { g_assert (GDATA_IS_FEED (feed)); g_assert_cmpuint (g_list_length (gdata_feed_get_entries (feed)), >, 0); g_object_unref (feed); } else { g_assert (feed == NULL); } } G_STMT_END); static void test_query_standard_feed_async_progress_closure (gconstpointer service) { GDataAsyncProgressClosure *data = g_slice_new0 (GDataAsyncProgressClosure); gulong filter_id; const gchar *ignore_query_param_values[] = { "publishedAfter", NULL, }; g_assert (service != NULL); filter_id = uhm_server_filter_ignore_parameter_values (mock_server, ignore_query_param_values); gdata_test_mock_server_start_trace (mock_server, "query-standard-feed-async-progress-closure"); data->main_loop = g_main_loop_new (NULL, TRUE); gdata_youtube_service_query_standard_feed_async (GDATA_YOUTUBE_SERVICE (service), GDATA_YOUTUBE_TOP_RATED_FEED, NULL, NULL, (GDataQueryProgressCallback) gdata_test_async_progress_callback, data, (GDestroyNotify) gdata_test_async_progress_closure_free, (GAsyncReadyCallback) gdata_test_async_progress_finish_callback, data); g_main_loop_run (data->main_loop); g_main_loop_unref (data->main_loop); /* Check that both callbacks were called exactly once */ g_assert_cmpuint (data->progress_destroy_notify_count, ==, 1); g_assert_cmpuint (data->async_ready_notify_count, ==, 1); g_slice_free (GDataAsyncProgressClosure, data); uhm_server_end_trace (mock_server); uhm_server_compare_messages_remove_filter (mock_server, filter_id); } static GDataYouTubeVideo * get_video_for_related (void) { GDataYouTubeVideo *video; GError *error = NULL; video = GDATA_YOUTUBE_VIDEO (gdata_parsable_new_from_json (GDATA_TYPE_YOUTUBE_VIDEO, "{" "'kind': 'youtube#video'," "'id': 'q1UPMEmCqZo'" "}", -1, &error)); g_assert_no_error (error); g_assert (GDATA_IS_YOUTUBE_VIDEO (video)); g_clear_error (&error); return video; } static void test_query_related (gconstpointer service) { GDataFeed *feed; GDataYouTubeVideo *video; GError *error = NULL; gdata_test_mock_server_start_trace (mock_server, "query-related"); video = get_video_for_related (); feed = gdata_youtube_service_query_related (GDATA_YOUTUBE_SERVICE (service), video, NULL, NULL, NULL, NULL, &error); g_assert_no_error (error); g_assert (GDATA_IS_FEED (feed)); g_clear_error (&error); /* TODO: check entries and feed properties */ g_object_unref (video); g_object_unref (feed); uhm_server_end_trace (mock_server); } GDATA_ASYNC_TEST_FUNCTIONS (query_related, void, G_STMT_START { GDataYouTubeVideo *video; video = get_video_for_related (); gdata_youtube_service_query_related_async (GDATA_YOUTUBE_SERVICE (service), video, NULL, cancellable, NULL, NULL, NULL, async_ready_callback, async_data); g_object_unref (video); } G_STMT_END, G_STMT_START { GDataFeed *feed; feed = gdata_service_query_finish (GDATA_SERVICE (obj), async_result, &error); if (error == NULL) { g_assert (GDATA_IS_FEED (feed)); /* TODO: Tests? */ g_object_unref (feed); } else { g_assert (feed == NULL); } } G_STMT_END); static void test_query_related_async_progress_closure (gconstpointer service) { GDataAsyncProgressClosure *data = g_slice_new0 (GDataAsyncProgressClosure); GDataYouTubeVideo *video; g_assert (service != NULL); gdata_test_mock_server_start_trace (mock_server, "query-related-async-progress-closure"); data->main_loop = g_main_loop_new (NULL, TRUE); video = get_video_for_related (); gdata_youtube_service_query_related_async (GDATA_YOUTUBE_SERVICE (service), video, NULL, NULL, (GDataQueryProgressCallback) gdata_test_async_progress_callback, data, (GDestroyNotify) gdata_test_async_progress_closure_free, (GAsyncReadyCallback) gdata_test_async_progress_finish_callback, data); g_object_unref (video); g_main_loop_run (data->main_loop); g_main_loop_unref (data->main_loop); /* Check that both callbacks were called exactly once */ g_assert_cmpuint (data->progress_destroy_notify_count, ==, 1); g_assert_cmpuint (data->async_ready_notify_count, ==, 1); g_slice_free (GDataAsyncProgressClosure, data); uhm_server_end_trace (mock_server); } typedef struct { GDataYouTubeService *service; GDataYouTubeVideo *video; GDataYouTubeVideo *updated_video; GFile *video_file; gchar *slug; gchar *content_type; } UploadData; static void set_up_upload (UploadData *data, gconstpointer service) { GDataMediaCategory *category; GFileInfo *file_info; const gchar * const tags[] = { "toast", "wedding", NULL }; gchar *path = NULL; GError *error = NULL; data->service = g_object_ref ((gpointer) service); /* Create the metadata for the video being uploaded */ data->video = gdata_youtube_video_new (NULL); gdata_entry_set_title (GDATA_ENTRY (data->video), "Bad Wedding Toast"); gdata_youtube_video_set_description (data->video, "I gave a bad toast at my friend's wedding."); category = gdata_media_category_new ("22", NULL, NULL); gdata_youtube_video_set_category (data->video, category); g_object_unref (category); gdata_youtube_video_set_keywords (data->video, tags); /* Get a file to upload */ /* TODO: fix the path */ path = g_test_build_filename (G_TEST_DIST, "sample.ogg", NULL); data->video_file = g_file_new_for_path (path); g_free (path); /* Get the file's info */ file_info = g_file_query_info (data->video_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, G_FILE_QUERY_INFO_NONE, NULL, &error); g_assert_no_error (error); g_assert (G_IS_FILE_INFO (file_info)); data->slug = g_strdup (g_file_info_get_display_name (file_info)); data->content_type = g_strdup (g_file_info_get_content_type (file_info)); g_object_unref (file_info); } static void tear_down_upload (UploadData *data, gconstpointer service) { gdata_test_mock_server_start_trace (mock_server, "teardown-upload"); /* Delete the uploaded video, if possible */ if (data->updated_video != NULL) { gdata_service_delete_entry (GDATA_SERVICE (service), gdata_youtube_service_get_primary_authorization_domain (), GDATA_ENTRY (data->updated_video), NULL, NULL); g_object_unref (data->updated_video); } g_object_unref (data->video); g_object_unref (data->video_file); g_free (data->slug); g_free (data->content_type); g_object_unref (data->service); uhm_server_end_trace (mock_server); } static void test_upload_simple (UploadData *data, gconstpointer service) { GDataUploadStream *upload_stream; GFileInputStream *file_stream; const gchar * const *tags, * const *tags2; gssize transfer_size; GError *error = NULL; gdata_test_mock_server_start_trace (mock_server, "upload-simple"); /* Prepare the upload stream */ upload_stream = gdata_youtube_service_upload_video (GDATA_YOUTUBE_SERVICE (service), data->video, data->slug, data->content_type, NULL, &error); g_assert_no_error (error); g_assert (GDATA_IS_UPLOAD_STREAM (upload_stream)); /* Get an input stream for the file */ file_stream = g_file_read (data->video_file, NULL, &error); g_assert_no_error (error); g_assert (G_IS_FILE_INPUT_STREAM (file_stream)); /* Upload the video */ transfer_size = g_output_stream_splice (G_OUTPUT_STREAM (upload_stream), G_INPUT_STREAM (file_stream), G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, NULL, &error); g_assert_no_error (error); g_assert_cmpint (transfer_size, >, 0); /* Finish off the upload */ data->updated_video = gdata_youtube_service_finish_video_upload (GDATA_YOUTUBE_SERVICE (service), upload_stream, &error); g_assert_no_error (error); g_assert (GDATA_IS_YOUTUBE_VIDEO (data->updated_video)); g_object_unref (file_stream); g_object_unref (upload_stream); /* Check the video's properties */ g_assert (gdata_entry_is_inserted (GDATA_ENTRY (data->updated_video))); g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (data->updated_video)), ==, gdata_entry_get_title (GDATA_ENTRY (data->video))); g_assert_cmpstr (gdata_youtube_video_get_description (data->updated_video), ==, gdata_youtube_video_get_description (data->video)); g_assert_cmpstr (gdata_media_category_get_category (gdata_youtube_video_get_category (data->updated_video)), ==, gdata_media_category_get_category (gdata_youtube_video_get_category (data->video))); tags = gdata_youtube_video_get_keywords (data->video); tags2 = gdata_youtube_video_get_keywords (data->updated_video); g_assert_cmpuint (g_strv_length ((gchar**) tags2), ==, g_strv_length ((gchar**) tags)); g_assert_cmpstr (tags2[0], ==, tags[0]); g_assert_cmpstr (tags2[1], ==, tags[1]); g_assert_cmpstr (tags2[2], ==, tags[2]); uhm_server_end_trace (mock_server); } GDATA_ASYNC_CLOSURE_FUNCTIONS (upload, UploadData); GDATA_ASYNC_TEST_FUNCTIONS (upload, UploadData, G_STMT_START { GDataUploadStream *upload_stream; GFileInputStream *file_stream; GError *error = NULL; /* Prepare the upload stream */ upload_stream = gdata_youtube_service_upload_video (GDATA_YOUTUBE_SERVICE (service), data->video, data->slug, data->content_type, cancellable, &error); g_assert_no_error (error); g_assert (GDATA_IS_UPLOAD_STREAM (upload_stream)); /* Get an input stream for the file */ file_stream = g_file_read (data->video_file, NULL, &error); g_assert_no_error (error); g_assert (G_IS_FILE_INPUT_STREAM (file_stream)); /* Upload the video asynchronously */ g_output_stream_splice_async (G_OUTPUT_STREAM (upload_stream), G_INPUT_STREAM (file_stream), G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, G_PRIORITY_DEFAULT, NULL, async_ready_callback, async_data); g_object_unref (file_stream); g_object_unref (upload_stream); } G_STMT_END, G_STMT_START { GOutputStream *stream = G_OUTPUT_STREAM (obj); const gchar * const *tags; const gchar * const *tags2; gssize transfer_size; GError *upload_error = NULL; /* Finish off the transfer */ transfer_size = g_output_stream_splice_finish (stream, async_result, &error); if (error == NULL) { g_assert_cmpint (transfer_size, >, 0); /* Finish off the upload */ data->updated_video = gdata_youtube_service_finish_video_upload (data->service, GDATA_UPLOAD_STREAM (stream), &upload_error); g_assert_no_error (upload_error); g_assert (GDATA_IS_YOUTUBE_VIDEO (data->updated_video)); /* Check the video's properties */ g_assert (gdata_entry_is_inserted (GDATA_ENTRY (data->updated_video))); g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (data->updated_video)), ==, gdata_entry_get_title (GDATA_ENTRY (data->video))); g_assert_cmpstr (gdata_youtube_video_get_description (data->updated_video), ==, gdata_youtube_video_get_description (data->video)); g_assert_cmpstr (gdata_media_category_get_category (gdata_youtube_video_get_category (data->updated_video)), ==, gdata_media_category_get_category (gdata_youtube_video_get_category (data->video))); tags = gdata_youtube_video_get_keywords (data->video); tags2 = gdata_youtube_video_get_keywords (data->updated_video); g_assert_cmpuint (g_strv_length ((gchar**) tags2), ==, g_strv_length ((gchar**) tags)); g_assert_cmpstr (tags2[0], ==, tags[0]); g_assert_cmpstr (tags2[1], ==, tags[1]); g_assert_cmpstr (tags2[2], ==, tags[2]); } else { g_assert_cmpint (transfer_size, ==, -1); /* Finish off the upload */ data->updated_video = gdata_youtube_service_finish_video_upload (data->service, GDATA_UPLOAD_STREAM (stream), &upload_error); g_assert_no_error (upload_error); g_assert (data->updated_video == NULL); } g_clear_error (&upload_error); } G_STMT_END); static void test_parsing_app_control (void) { GDataYouTubeVideo *video; GDataYouTubeState *state; GError *error = NULL; video = GDATA_YOUTUBE_VIDEO (gdata_parsable_new_from_json (GDATA_TYPE_YOUTUBE_VIDEO, "{" "'kind': 'youtube#video'," "'etag': '\"tbWC5XrSXxe1WOAx6MK9z4hHSU8/X_byq2BdOVgHzCA-ScpZbTWmgfQ\"'," "'id': 'JAagedeKdcQ'," "'snippet': {" "'publishedAt': '2006-05-16T14:06:37.000Z'," "'channelId': 'UCCS6UQvicRHyn1whEUDEMUQ'," "'title': 'Judas Priest - Painkiller'," "'description': 'Videoclip de Judas Priest'," "'thumbnails': {" "'default': {" "'url': 'https://i.ytimg.com/vi/JAagedeKdcQ/default.jpg'," "'width': 120," "'height': 90" "}," "'medium': {" "'url': 'https://i.ytimg.com/vi/JAagedeKdcQ/mqdefault.jpg'," "'width': 320," "'height': 180" "}," "'high': {" "'url': 'https://i.ytimg.com/vi/JAagedeKdcQ/hqdefault.jpg'," "'width': 480," "'height': 360" "}" "}," "'channelTitle': 'eluves'," "'categoryId': '10'," "'liveBroadcastContent': 'none'," "'localized': {" "'title': 'Judas Priest - Painkiller'," "'description': 'Videoclip de Judas Priest'" "}" "}," "'contentDetails': {" "'duration': 'PT6M'," "'dimension': '2d'," "'definition': 'sd'," "'caption': 'false'," "'licensedContent': false," "'regionRestriction': {" "'blocked': [" "'RU'," "'RW'," "'RS'," "'RO'," "'RE'," "'BL'," "'BM'," "'BN'," "'BO'," "'JP'," "'BI'," "'BJ'," "'BD'," "'BE'," "'BF'," "'BG'," "'YT'," "'BB'," "'CX'," "'JE'," "'BY'," "'BZ'," "'BT'," "'JM'," "'BV'," "'BW'," "'YE'," "'BQ'," "'BR'," "'BS'," "'IM'," "'IL'," "'IO'," "'IN'," "'IE'," "'ID'," "'QA'," "'TM'," "'IQ'," "'IS'," "'IR'," "'IT'," "'TK'," "'AE'," "'AD'," "'AG'," "'AF'," "'AI'," "'AM'," "'AL'," "'AO'," "'AQ'," "'AS'," "'AR'," "'AU'," "'AT'," "'AW'," "'TG'," "'AX'," "'AZ'," "'PR'," "'HK'," "'HN'," "'PW'," "'PT'," "'HM'," "'PY'," "'PA'," "'PF'," "'PG'," "'PE'," "'HR'," "'PK'," "'PH'," "'PN'," "'HT'," "'HU'," "'OM'," "'WS'," "'WF'," "'BH'," "'KP'," "'TT'," "'GG'," "'GF'," "'GE'," "'GD'," "'GB'," "'VN'," "'VA'," "'GM'," "'VC'," "'VE'," "'GI'," "'VG'," "'GW'," "'GU'," "'GT'," "'GS'," "'GR'," "'GQ'," "'GP'," "'VU'," "'GY'," "'NA'," "'NC'," "'NE'," "'NF'," "'NG'," "'NI'," "'NL'," "'BA'," "'NO'," "'NP'," "'NR'," "'NU'," "'NZ'," "'PM'," "'UM'," "'TV'," "'UG'," "'UA'," "'FI'," "'FJ'," "'FK'," "'UY'," "'FM'," "'CN'," "'UZ'," "'US'," "'ME'," "'MD'," "'MG'," "'MF'," "'MA'," "'MC'," "'VI'," "'MM'," "'ML'," "'MO'," "'FO'," "'MH'," "'MK'," "'MU'," "'MT'," "'MW'," "'MV'," "'MQ'," "'MP'," "'MS'," "'MR'," "'CO'," "'CV'," "'MY'," "'MX'," "'MZ'," "'TN'," "'TO'," "'TL'," "'JO'," "'TJ'," "'GA'," "'TH'," "'TF'," "'ET'," "'TD'," "'TC'," "'ES'," "'ER'," "'TZ'," "'EH'," "'GN'," "'EE'," "'TW'," "'EG'," "'TR'," "'CA'," "'EC'," "'GL'," "'LB'," "'LC'," "'LA'," "'MN'," "'LK'," "'LI'," "'LV'," "'LT'," "'LU'," "'LR'," "'LS'," "'PS'," "'KZ'," "'GH'," "'LY'," "'DZ'," "'DO'," "'DM'," "'DJ'," "'PL'," "'DK'," "'DE'," "'SZ'," "'SY'," "'SX'," "'SS'," "'SR'," "'SV'," "'ST'," "'SK'," "'SJ'," "'SI'," "'SH'," "'SO'," "'SN'," "'SM'," "'SL'," "'SC'," "'SB'," "'SA'," "'FR'," "'SG'," "'SE'," "'SD'," "'CK'," "'KR'," "'CI'," "'CH'," "'KW'," "'ZA'," "'CM'," "'CL'," "'CC'," "'ZM'," "'KY'," "'CG'," "'CF'," "'CD'," "'CZ'," "'CY'," "'ZW'," "'KG'," "'CU'," "'KE'," "'CR'," "'KI'," "'KH'," "'CW'," "'KN'," "'KM'" "]" "}" "}," "'status': {" "'uploadStatus': 'processed'," "'privacyStatus': 'private'," "'license': 'youtube'," "'embeddable': true," "'publicStatsViewable': true" "}," "'statistics': {" "'viewCount': '4369107'," "'likeCount': '13619'," "'dislikeCount': '440'," "'favoriteCount': '0'," "'commentCount': '11181'" "}" "}", -1, &error)); g_assert_no_error (error); g_assert (GDATA_IS_YOUTUBE_VIDEO (video)); g_clear_error (&error); /* Test the app:control values */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_assert (gdata_youtube_video_is_draft (video) == TRUE); G_GNUC_END_IGNORE_DEPRECATIONS state = gdata_youtube_video_get_state (video); g_assert_cmpstr (gdata_youtube_state_get_name (state), ==, NULL); g_assert_cmpstr (gdata_youtube_state_get_message (state), ==, NULL); g_assert (gdata_youtube_state_get_reason_code (state) == NULL); g_assert (gdata_youtube_state_get_help_uri (state) == NULL); /* TODO: more tests on entry properties */ g_object_unref (video); } static void test_parsing_yt_recorded (void) { GDataYouTubeVideo *video; gint64 recorded; GError *error = NULL; video = GDATA_YOUTUBE_VIDEO (gdata_parsable_new_from_json (GDATA_TYPE_YOUTUBE_VIDEO, "{" "'kind': 'youtube#video'," "'etag': '\"tbWC5XrSXxe1WOAx6MK9z4hHSU8/X_byq2BdOVgHzCA-ScpZbTWmgfQ\"'," "'id': 'JAagedeKdcQ'," "'snippet': {" "'publishedAt': '2006-05-16T14:06:37.000Z'," "'channelId': 'UCCS6UQvicRHyn1whEUDEMUQ'," "'title': 'Judas Priest - Painkiller'," "'description': 'Videoclip de Judas Priest'," "'channelTitle': 'eluves'," "'categoryId': '10'," "'liveBroadcastContent': 'none'," "'localized': {" "'title': 'Judas Priest - Painkiller'," "'description': 'Videoclip de Judas Priest'" "}" "}," "'recordingDetails': {" "'recordingDate': '2003-08-03'" "}" "}", -1, &error)); g_assert_no_error (error); g_assert (GDATA_IS_YOUTUBE_VIDEO (video)); g_clear_error (&error); /* Test the recorded date */ recorded = gdata_youtube_video_get_recorded (video); g_assert_cmpint (recorded, ==, 1059868800); /* Update the state and see if the XML's written out OK */ recorded = 1128229200; gdata_youtube_video_set_recorded (video, recorded); /* Check the XML */ gdata_test_assert_json (video, "{" "'kind': 'youtube#video'," "'etag': '\"tbWC5XrSXxe1WOAx6MK9z4hHSU8/X_byq2BdOVgHzCA-ScpZbTWmgfQ\"'," "'id': 'JAagedeKdcQ'," "'selfLink': 'https://www.googleapis.com/youtube/v3/videos?id=JAagedeKdcQ'," "'title': 'Judas Priest - Painkiller'," "'description': 'Videoclip de Judas Priest'," "'snippet': {" "'title': 'Judas Priest - Painkiller'," "'description': 'Videoclip de Judas Priest'," "'categoryId': '10'" "}," "'status': {" "'privacyStatus': 'public'" "}," "'recordingDetails': {" "'recordingDate': '2005-10-02'" "}" "}"); /* TODO: more tests on entry properties */ g_object_unref (video); } static void test_parsing_yt_access_control (void) { GDataYouTubeVideo *video; GError *error = NULL; video = GDATA_YOUTUBE_VIDEO (gdata_parsable_new_from_json (GDATA_TYPE_YOUTUBE_VIDEO, "{" "'kind': 'youtube#video'," "'id': 'JAagedeKdcQ'," "'status': {" "'privacyStatus': 'public'," "'embeddable': false" "}" "}", -1, &error)); g_assert_no_error (error); g_assert (GDATA_IS_YOUTUBE_VIDEO (video)); g_clear_error (&error); /* Test the access controls */ g_assert_cmpint (gdata_youtube_video_get_access_control (video, GDATA_YOUTUBE_ACTION_RATE), ==, GDATA_YOUTUBE_PERMISSION_DENIED); g_assert_cmpint (gdata_youtube_video_get_access_control (video, GDATA_YOUTUBE_ACTION_COMMENT), ==, GDATA_YOUTUBE_PERMISSION_DENIED); g_assert_cmpint (gdata_youtube_video_get_access_control (video, GDATA_YOUTUBE_ACTION_COMMENT_VOTE), ==, GDATA_YOUTUBE_PERMISSION_DENIED); g_assert_cmpint (gdata_youtube_video_get_access_control (video, GDATA_YOUTUBE_ACTION_VIDEO_RESPOND), ==, GDATA_YOUTUBE_PERMISSION_DENIED); g_assert_cmpint (gdata_youtube_video_get_access_control (video, GDATA_YOUTUBE_ACTION_EMBED), ==, GDATA_YOUTUBE_PERMISSION_DENIED); g_assert_cmpint (gdata_youtube_video_get_access_control (video, GDATA_YOUTUBE_ACTION_SYNDICATE), ==, GDATA_YOUTUBE_PERMISSION_DENIED); g_assert_cmpint (gdata_youtube_video_get_access_control (video, "list"), ==, GDATA_YOUTUBE_PERMISSION_ALLOWED); /* Update some of them and see if the JSON’s written out OK */ gdata_youtube_video_set_access_control (video, "list", GDATA_YOUTUBE_PERMISSION_DENIED); gdata_youtube_video_set_access_control (video, GDATA_YOUTUBE_ACTION_EMBED, GDATA_YOUTUBE_PERMISSION_ALLOWED); /* Check the JSON */ gdata_test_assert_json (video, "{" "'kind': 'youtube#video'," "'id': 'JAagedeKdcQ'," "'selfLink': 'https://www.googleapis.com/youtube/v3/videos?id=JAagedeKdcQ'," "'title': null," "'snippet': {}," "'status': {" "'privacyStatus': 'unlisted'," "'embeddable': true" "}," "'recordingDetails': {}" "}"); g_object_unref (video); } static void test_parsing_yt_category (void) { GDataYouTubeCategory *category; gboolean assignable, deprecated; GError *error = NULL; /* Test a non-deprecated category */ category = GDATA_YOUTUBE_CATEGORY (gdata_parsable_new_from_xml (GDATA_TYPE_YOUTUBE_CATEGORY, "" "" "" "", -1, &error)); g_assert_no_error (error); g_assert (GDATA_IS_YOUTUBE_CATEGORY (category)); g_clear_error (&error); /* Test the category's properties */ g_assert (gdata_youtube_category_is_assignable (category) == TRUE); g_assert (gdata_youtube_category_is_browsable (category, "CZ") == TRUE); g_assert (gdata_youtube_category_is_browsable (category, "AU") == TRUE); g_assert (gdata_youtube_category_is_browsable (category, "HK") == TRUE); g_assert (gdata_youtube_category_is_browsable (category, "GB") == FALSE); g_assert (gdata_youtube_category_is_deprecated (category) == FALSE); /* Test the properties the other way */ g_object_get (category, "is-assignable", &assignable, "is-deprecated", &deprecated, NULL); g_assert (assignable == TRUE); g_assert (deprecated == FALSE); g_object_unref (category); /* Test a deprecated category */ category = GDATA_YOUTUBE_CATEGORY (gdata_parsable_new_from_xml (GDATA_TYPE_YOUTUBE_CATEGORY, "" "" "", -1, &error)); g_assert_no_error (error); g_assert (GDATA_IS_YOUTUBE_CATEGORY (category)); g_clear_error (&error); /* Test the category's properties */ g_assert (gdata_youtube_category_is_assignable (category) == FALSE); g_assert (gdata_youtube_category_is_browsable (category, "CZ") == FALSE); g_assert (gdata_youtube_category_is_browsable (category, "AU") == FALSE); g_assert (gdata_youtube_category_is_browsable (category, "HK") == FALSE); g_assert (gdata_youtube_category_is_browsable (category, "GB") == FALSE); g_assert (gdata_youtube_category_is_deprecated (category) == TRUE); g_object_unref (category); } static void test_parsing_georss_where (void) { GDataYouTubeVideo *video; gdouble latitude, longitude; GError *error = NULL; video = GDATA_YOUTUBE_VIDEO (gdata_parsable_new_from_json (GDATA_TYPE_YOUTUBE_VIDEO, "{" "'kind': 'youtube#video'," "'id': 'JAagedeKdcQ'," "'recordingDetails': {" "'location': {" "'latitude': 41.14556884765625," "'longitude': -8.63525390625" "}" "}" "}", -1, &error)); g_assert_no_error (error); g_assert (GDATA_IS_YOUTUBE_VIDEO (video)); g_clear_error (&error); /* Test the coordinates */ gdata_youtube_video_get_coordinates (video, &latitude, &longitude); g_assert_cmpfloat (latitude, ==, 41.14556884765625); g_assert_cmpfloat (longitude, ==, -8.63525390625); /* Update them and see if they're set OK and the JSON’s written out OK */ gdata_youtube_video_set_coordinates (video, 5.5, 6.5); g_object_get (G_OBJECT (video), "latitude", &latitude, "longitude", &longitude, NULL); g_assert_cmpfloat (latitude, ==, 5.5); g_assert_cmpfloat (longitude, ==, 6.5); /* Check the JSON */ gdata_test_assert_json (video, "{" "'kind': 'youtube#video'," "'id': 'JAagedeKdcQ'," "'selfLink': 'https://www.googleapis.com/youtube/v3/videos?id=JAagedeKdcQ'," "'title': null," "'snippet': {}," "'status': {" "'privacyStatus': 'public'" "}," "'recordingDetails': {" "'location': {" "'latitude': 5.5," "'longitude': 6.5" "}" "}" "}"); /* Unset the properties and ensure they’re removed from the JSON */ gdata_youtube_video_set_coordinates (video, G_MAXDOUBLE, G_MAXDOUBLE); gdata_youtube_video_get_coordinates (video, &latitude, &longitude); g_assert_cmpfloat (latitude, ==, G_MAXDOUBLE); g_assert_cmpfloat (longitude, ==, G_MAXDOUBLE); /* Check the JSON */ gdata_test_assert_json (video, "{" "'kind': 'youtube#video'," "'id': 'JAagedeKdcQ'," "'selfLink': 'https://www.googleapis.com/youtube/v3/videos?id=JAagedeKdcQ'," "'title': null," "'snippet': {}," "'status': {" "'privacyStatus': 'public'" "}," "'recordingDetails': {}" "}"); g_object_unref (video); } static void test_parsing_ratings (void) { GDataYouTubeVideo *video; GError *error = NULL; /* Parse all ratings */ video = GDATA_YOUTUBE_VIDEO (gdata_parsable_new_from_json (GDATA_TYPE_YOUTUBE_VIDEO, "{" "'kind': 'youtube#video'," "'id': 'JAagedeKdcQ'," "'contentDetails': {" "'contentRating': {" "'mpaaRating': 'mpaaPg'," "'tvpgRating': 'tvpgPg'" "}" "}" "}", -1, &error)); g_assert_no_error (error); g_assert (GDATA_IS_YOUTUBE_VIDEO (video)); g_clear_error (&error); /* Check the ratings, and check that we haven't ended up with a country restriction */ g_assert_cmpstr (gdata_youtube_video_get_media_rating (video, GDATA_YOUTUBE_RATING_TYPE_MPAA), ==, "pg"); g_assert_cmpstr (gdata_youtube_video_get_media_rating (video, GDATA_YOUTUBE_RATING_TYPE_V_CHIP), ==, "tv-pg"); g_assert (gdata_youtube_video_is_restricted_in_country (video, "US") == FALSE); g_object_unref (video); /* Parse a video with one rating missing and see what happens */ video = GDATA_YOUTUBE_VIDEO (gdata_parsable_new_from_json (GDATA_TYPE_YOUTUBE_VIDEO, "{" "'kind': 'youtube#video'," "'id': 'JAagedeKdcQ'," "'contentDetails': {" "'contentRating': {" "'tvpgRating': 'tvpgY7Fv'" "}" "}" "}", -1, &error)); g_assert_no_error (error); g_assert (GDATA_IS_YOUTUBE_VIDEO (video)); g_clear_error (&error); /* Check the ratings again */ g_assert_cmpstr (gdata_youtube_video_get_media_rating (video, GDATA_YOUTUBE_RATING_TYPE_MPAA), ==, NULL); g_assert_cmpstr (gdata_youtube_video_get_media_rating (video, GDATA_YOUTUBE_RATING_TYPE_V_CHIP), ==, "tv-y7-fv"); /* Check that calling with an arbitrary rating type returns NULL. * %GDATA_YOUTUBE_RATING_TYPE_SIMPLE is no longer supported. */ g_assert_cmpstr (gdata_youtube_video_get_media_rating (video, "fooish bar"), ==, NULL); g_assert_cmpstr (gdata_youtube_video_get_media_rating (video, GDATA_YOUTUBE_RATING_TYPE_SIMPLE), ==, NULL); g_object_unref (video); } static void test_video_escaping (void) { GDataYouTubeVideo *video; const gchar * const keywords[] = { "", "keyword2 & stuff, things", NULL }; video = gdata_youtube_video_new (NULL); gdata_youtube_video_set_location (video, "\"Here\" & 'there'"); gdata_youtube_video_set_access_control (video, "", GDATA_YOUTUBE_PERMISSION_ALLOWED); gdata_youtube_video_set_keywords (video, keywords); gdata_youtube_video_set_description (video, "Description & 'stuff'."); gdata_youtube_video_set_aspect_ratio (video, "4 & 3"); /* Check the outputted JSON is escaped properly */ gdata_test_assert_json (video, "{" "'kind': 'youtube#video'," "'title': null," "'description': \"Description & 'stuff'.\"," "'snippet': {" "'description': \"Description & 'stuff'.\"," "'tags': [" "''," "'keyword2 & stuff, things'" "]" "}," "'status': {" "'privacyStatus': 'public'" "}," "'recordingDetails': {" "'locationDescription': \"\\\"Here\\\" & 'there'\"" "}" "}"); g_object_unref (video); } /* Check that a newly-constructed video does not output a location in its * JSON or properties. */ static void test_video_location (void) { GDataYouTubeVideo *video; gdouble latitude, longitude; video = gdata_youtube_video_new (NULL); g_assert_null (gdata_youtube_video_get_location (video)); /* Latitude and longitude should be outside the valid ranges. */ gdata_youtube_video_get_coordinates (video, &latitude, &longitude); g_assert (latitude < -90.0 || latitude > 90.0); g_assert (longitude < -180.0 || longitude > 180.0); /* Check the outputted JSON is escaped properly */ gdata_test_assert_json (video, "{" "'title': null," "'kind': 'youtube#video'," "'snippet': {}," "'status': {" "'privacyStatus': 'public'" "}," "'recordingDetails': {}" "}"); g_object_unref (video); } static void test_comment_get_json (void) { GDataYouTubeComment *comment_; comment_ = gdata_youtube_comment_new (NULL); gdata_entry_set_content (GDATA_ENTRY (comment_), "This is a comment with & 'stüff'."); gdata_youtube_comment_set_parent_comment_uri (comment_, "http://example.com/?foo=bar&baz=shizzle"); /* Check the outputted JSON is OK */ gdata_test_assert_json (comment_, "{" "'kind': 'youtube#commentThread'," "'snippet' : {" "'topLevelComment': {" "'kind': 'youtube#comment'," "'snippet': {" "'textOriginal': \"This is a comment with & 'stüff'.\"," "'parentId': 'http://example.com/?foo=bar&baz=shizzle'" "}" "}" "}" "}"); g_object_unref (comment_); } static void notify_cb (GDataYouTubeComment *comment_, GParamSpec *pspec, guint *notification_count) { *notification_count = *notification_count + 1; } static void test_comment_properties_parent_comment_uri (void) { GDataYouTubeComment *comment_; guint notification_count = 0; gchar *parent_comment_uri; comment_ = gdata_youtube_comment_new (NULL); g_signal_connect (comment_, "notify::parent-comment-uri", (GCallback) notify_cb, ¬ification_count); /* Default. */ g_assert (gdata_youtube_comment_get_parent_comment_uri (comment_) == NULL); /* Set the property. */ gdata_youtube_comment_set_parent_comment_uri (comment_, "foo"); g_assert_cmpuint (notification_count, ==, 1); g_assert_cmpstr (gdata_youtube_comment_get_parent_comment_uri (comment_), ==, "foo"); /* Get the property a different way. */ g_object_get (G_OBJECT (comment_), "parent-comment-uri", &parent_comment_uri, NULL); g_assert_cmpstr (parent_comment_uri, ==, "foo"); g_free (parent_comment_uri); /* Set the property a different way. */ g_object_set (G_OBJECT (comment_), "parent-comment-uri", "bar", NULL); g_assert_cmpuint (notification_count, ==, 2); /* Set the property to the same value. */ gdata_youtube_comment_set_parent_comment_uri (comment_, "bar"); g_assert_cmpuint (notification_count, ==, 2); /* Set the property back to NULL. */ gdata_youtube_comment_set_parent_comment_uri (comment_, NULL); g_assert_cmpuint (notification_count, ==, 3); g_assert (gdata_youtube_comment_get_parent_comment_uri (comment_) == NULL); g_object_unref (comment_); } static gchar * build_this_week_date_str (void) { GTimeVal tv; g_get_current_time (&tv); tv.tv_sec -= 7 * 24 * 60 * 60; /* this week */ tv.tv_usec = 0; /* pointless accuracy */ return g_time_val_to_iso8601 (&tv); } static void test_query_uri (void) { gdouble latitude, longitude, radius; gboolean has_location; gchar *query_uri; GDataYouTubeQuery *query = gdata_youtube_query_new ("q"); gchar *this_week_date_str, *expected_uri; G_GNUC_BEGIN_IGNORE_DEPRECATIONS /* This should not appear in the query because it is deprecated. */ gdata_youtube_query_set_format (query, GDATA_YOUTUBE_FORMAT_RTSP_H263_AMR); g_assert_cmpuint (gdata_youtube_query_get_format (query), ==, 1); /* Location */ gdata_youtube_query_set_location (query, 45.01364, -97.12356, 112.5, TRUE); gdata_youtube_query_get_location (query, &latitude, &longitude, &radius, &has_location); g_assert_cmpfloat (latitude, ==, 45.01364); g_assert_cmpfloat (longitude, ==, -97.12356); g_assert_cmpfloat (radius, ==, 112.5); g_assert (has_location == TRUE); query_uri = gdata_query_get_query_uri (GDATA_QUERY (query), "http://example.com"); g_assert_cmpstr (query_uri, ==, "http://example.com?q=q&safeSearch=none&location=45.013640000000002,-97.123559999999998&locationRadius=112.5m"); g_free (query_uri); /* This used to set the has-location parameter in the query, but that’s * no longer supported by Google, so it should be the same as the * following query. */ gdata_youtube_query_set_location (query, G_MAXDOUBLE, 0.6672, 52.8, TRUE); query_uri = gdata_query_get_query_uri (GDATA_QUERY (query), "http://example.com"); g_assert_cmpstr (query_uri, ==, "http://example.com?q=q&safeSearch=none"); g_free (query_uri); gdata_youtube_query_set_location (query, G_MAXDOUBLE, G_MAXDOUBLE, 0.0, FALSE); query_uri = gdata_query_get_query_uri (GDATA_QUERY (query), "http://example.com"); g_assert_cmpstr (query_uri, ==, "http://example.com?q=q&safeSearch=none"); g_free (query_uri); /* Language; this should not appear in the query as it is no longer * supported. */ gdata_youtube_query_set_language (query, "fr"); g_assert_cmpstr (gdata_youtube_query_get_language (query), ==, "fr"); gdata_youtube_query_set_order_by (query, "relevance_lang_fr"); g_assert_cmpstr (gdata_youtube_query_get_order_by (query), ==, "relevance_lang_fr"); gdata_youtube_query_set_restriction (query, "192.168.0.1"); g_assert_cmpstr (gdata_youtube_query_get_restriction (query), ==, "192.168.0.1"); query_uri = gdata_query_get_query_uri (GDATA_QUERY (query), "http://example.com"); g_assert_cmpstr (query_uri, ==, "http://example.com?q=q&safeSearch=none&order=relevance®ionCode=192.168.0.1"); g_free (query_uri); gdata_youtube_query_set_safe_search (query, GDATA_YOUTUBE_SAFE_SEARCH_STRICT); g_assert_cmpuint (gdata_youtube_query_get_safe_search (query), ==, GDATA_YOUTUBE_SAFE_SEARCH_STRICT); query_uri = gdata_query_get_query_uri (GDATA_QUERY (query), "http://example.com"); g_assert_cmpstr (query_uri, ==, "http://example.com?q=q&safeSearch=strict&order=relevance®ionCode=192.168.0.1"); g_free (query_uri); /* Deprecated and unused: */ gdata_youtube_query_set_sort_order (query, GDATA_YOUTUBE_SORT_ASCENDING); g_assert_cmpuint (gdata_youtube_query_get_sort_order (query), ==, GDATA_YOUTUBE_SORT_ASCENDING); gdata_youtube_query_set_age (query, GDATA_YOUTUBE_AGE_THIS_WEEK); g_assert_cmpuint (gdata_youtube_query_get_age (query), ==, GDATA_YOUTUBE_AGE_THIS_WEEK); /* Deprecated and unused: */ gdata_youtube_query_set_uploader (query, GDATA_YOUTUBE_UPLOADER_PARTNER); g_assert_cmpuint (gdata_youtube_query_get_uploader (query), ==, GDATA_YOUTUBE_UPLOADER_PARTNER); gdata_youtube_query_set_license (query, GDATA_YOUTUBE_LICENSE_CC); g_assert_cmpstr (gdata_youtube_query_get_license (query), ==, GDATA_YOUTUBE_LICENSE_CC); /* Check the built URI with a normal feed URI */ query_uri = gdata_query_get_query_uri (GDATA_QUERY (query), "http://example.com"); this_week_date_str = build_this_week_date_str (); expected_uri = g_strdup_printf ("http://example.com?q=q&publishedAfter=%s&safeSearch=strict&order=relevance®ionCode=192.168.0.1&videoLicense=creativeCommon", this_week_date_str); g_assert_cmpstr (query_uri, ==, expected_uri); g_free (this_week_date_str); g_free (expected_uri); g_free (query_uri); /* …and with a feed URI with pre-existing arguments */ query_uri = gdata_query_get_query_uri (GDATA_QUERY (query), "http://example.com?foobar=shizzle"); this_week_date_str = build_this_week_date_str (); expected_uri = g_strdup_printf ("http://example.com?foobar=shizzle&q=q&publishedAfter=%s&safeSearch=strict&order=relevance®ionCode=192.168.0.1&videoLicense=creativeCommon", this_week_date_str); g_assert_cmpstr (query_uri, ==, expected_uri); g_free (this_week_date_str); g_free (expected_uri); g_free (query_uri); g_object_unref (query); G_GNUC_END_IGNORE_DEPRECATIONS } static void test_query_etag (void) { GDataYouTubeQuery *query = gdata_youtube_query_new (NULL); /* Test that setting any property will unset the ETag */ g_test_bug ("613529"); G_GNUC_BEGIN_IGNORE_DEPRECATIONS #define CHECK_ETAG(C) \ gdata_query_set_etag (GDATA_QUERY (query), "foobar"); \ (C); \ g_assert (gdata_query_get_etag (GDATA_QUERY (query)) == NULL); CHECK_ETAG (gdata_youtube_query_set_format (query, GDATA_YOUTUBE_FORMAT_RTSP_H263_AMR)) CHECK_ETAG (gdata_youtube_query_set_location (query, 0.0, 65.0, 15.0, TRUE)) CHECK_ETAG (gdata_youtube_query_set_language (query, "British English")) CHECK_ETAG (gdata_youtube_query_set_order_by (query, "shizzle")) CHECK_ETAG (gdata_youtube_query_set_restriction (query, "restriction")) CHECK_ETAG (gdata_youtube_query_set_safe_search (query, GDATA_YOUTUBE_SAFE_SEARCH_MODERATE)) CHECK_ETAG (gdata_youtube_query_set_sort_order (query, GDATA_YOUTUBE_SORT_DESCENDING)) CHECK_ETAG (gdata_youtube_query_set_age (query, GDATA_YOUTUBE_AGE_THIS_WEEK)) CHECK_ETAG (gdata_youtube_query_set_uploader (query, GDATA_YOUTUBE_UPLOADER_PARTNER)) CHECK_ETAG (gdata_youtube_query_set_license (query, GDATA_YOUTUBE_LICENSE_STANDARD)) #undef CHECK_ETAG g_object_unref (query); G_GNUC_END_IGNORE_DEPRECATIONS } static void test_query_single (gconstpointer service) { GDataYouTubeVideo *video; GError *error = NULL; gdata_test_mock_server_start_trace (mock_server, "query-single"); video = GDATA_YOUTUBE_VIDEO (gdata_service_query_single_entry (GDATA_SERVICE (service), gdata_youtube_service_get_primary_authorization_domain (), "tag:youtube.com,2008:video:_LeQuMpwbW4", NULL, GDATA_TYPE_YOUTUBE_VIDEO, NULL, &error)); g_assert_no_error (error); g_assert (video != NULL); g_assert (GDATA_IS_YOUTUBE_VIDEO (video)); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_assert_cmpstr (gdata_youtube_video_get_video_id (video), ==, "_LeQuMpwbW4"); g_assert_cmpstr (gdata_entry_get_id (GDATA_ENTRY (video)), ==, "_LeQuMpwbW4"); G_GNUC_END_IGNORE_DEPRECATIONS g_clear_error (&error); g_object_unref (video); uhm_server_end_trace (mock_server); } GDATA_ASYNC_TEST_FUNCTIONS (query_single, void, G_STMT_START { gdata_service_query_single_entry_async (GDATA_SERVICE (service), gdata_youtube_service_get_primary_authorization_domain (), "tag:youtube.com,2008:video:_LeQuMpwbW4", NULL, GDATA_TYPE_YOUTUBE_VIDEO, cancellable, async_ready_callback, async_data); } G_STMT_END, G_STMT_START { GDataYouTubeVideo *video; video = GDATA_YOUTUBE_VIDEO (gdata_service_query_single_entry_finish (GDATA_SERVICE (obj), async_result, &error)); if (error == NULL) { G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_assert (GDATA_IS_YOUTUBE_VIDEO (video)); g_assert_cmpstr (gdata_youtube_video_get_video_id (video), ==, "_LeQuMpwbW4"); g_assert_cmpstr (gdata_entry_get_id (GDATA_ENTRY (video)), ==, "_LeQuMpwbW4"); G_GNUC_END_IGNORE_DEPRECATIONS g_object_unref (video); } else { g_assert (video == NULL); } } G_STMT_END); typedef struct { GDataYouTubeVideo *video; } CommentData; static void set_up_comment (CommentData *data, gconstpointer service) { gdata_test_mock_server_start_trace (mock_server, "setup-comment"); /* Get a video known to have comments on it. */ data->video = GDATA_YOUTUBE_VIDEO (gdata_service_query_single_entry (GDATA_SERVICE (service), gdata_youtube_service_get_primary_authorization_domain (), "tag:youtube.com,2008:video:RzR2k8yo4NY", NULL, GDATA_TYPE_YOUTUBE_VIDEO, NULL, NULL)); g_assert (GDATA_IS_YOUTUBE_VIDEO (data->video)); uhm_server_end_trace (mock_server); } static void tear_down_comment (CommentData *data, gconstpointer service) { g_object_unref (data->video); } static void assert_comments_feed (GDataFeed *comments_feed) { GList *comments; g_assert (GDATA_IS_FEED (comments_feed)); for (comments = gdata_feed_get_entries (comments_feed); comments != NULL; comments = comments->next) { GList *authors; GDataYouTubeComment *comment_ = GDATA_YOUTUBE_COMMENT (comments->data); /* We can't do much more than this, since we can't reasonably add test comments to public videos, and can't upload a new video * for each test since it has to go through moderation. */ g_assert_cmpstr (gdata_entry_get_content (GDATA_ENTRY (comment_)), !=, NULL); g_assert_cmpuint (g_list_length (gdata_entry_get_authors (GDATA_ENTRY (comment_))), >, 0); for (authors = gdata_entry_get_authors (GDATA_ENTRY (comment_)); authors != NULL; authors = authors->next) { GDataAuthor *author = GDATA_AUTHOR (authors->data); /* Again, we can't test these much. */ g_assert_cmpstr (gdata_author_get_name (author), !=, NULL); g_assert_cmpstr (gdata_author_get_uri (author), !=, NULL); } } } static void test_comment_query (CommentData *data, gconstpointer service) { GDataFeed *comments_feed; GError *error = NULL; gdata_test_mock_server_start_trace (mock_server, "comment-query"); /* Get the comments feed for the video */ comments_feed = gdata_commentable_query_comments (GDATA_COMMENTABLE (data->video), GDATA_SERVICE (service), NULL, NULL, NULL, NULL, &error); g_assert_no_error (error); g_clear_error (&error); assert_comments_feed (comments_feed); g_object_unref (comments_feed); uhm_server_end_trace (mock_server); } GDATA_ASYNC_CLOSURE_FUNCTIONS (comment, CommentData); GDATA_ASYNC_TEST_FUNCTIONS (comment_query, CommentData, G_STMT_START { gdata_commentable_query_comments_async (GDATA_COMMENTABLE (data->video), GDATA_SERVICE (service), NULL, cancellable, NULL, NULL, NULL, async_ready_callback, async_data); } G_STMT_END, G_STMT_START { GDataFeed *comments_feed; comments_feed = gdata_commentable_query_comments_finish (GDATA_COMMENTABLE (obj), async_result, &error); if (error == NULL) { assert_comments_feed (comments_feed); g_object_unref (comments_feed); } else { g_assert (comments_feed == NULL); } } G_STMT_END); /* Test that the progress callbacks from gdata_commentable_query_comments_async() are called correctly. * We take a CommentData so that we can guarantee the video exists, but we don't use it much as we don't actually care about the specific * video. */ static void test_comment_query_async_progress_closure (CommentData *query_data, gconstpointer service) { GDataAsyncProgressClosure *data = g_slice_new0 (GDataAsyncProgressClosure); gdata_test_mock_server_start_trace (mock_server, "comment-query-async-progress-closure"); data->main_loop = g_main_loop_new (NULL, TRUE); gdata_commentable_query_comments_async (GDATA_COMMENTABLE (query_data->video), GDATA_SERVICE (service), NULL, NULL, (GDataQueryProgressCallback) gdata_test_async_progress_callback, data, (GDestroyNotify) gdata_test_async_progress_closure_free, (GAsyncReadyCallback) gdata_test_async_progress_finish_callback, data); g_main_loop_run (data->main_loop); g_main_loop_unref (data->main_loop); /* Check that both callbacks were called exactly once */ g_assert_cmpuint (data->progress_destroy_notify_count, ==, 1); g_assert_cmpuint (data->async_ready_notify_count, ==, 1); g_slice_free (GDataAsyncProgressClosure, data); uhm_server_end_trace (mock_server); } typedef struct { CommentData parent; GDataYouTubeComment *comment; } InsertCommentData; static void set_up_insert_comment (InsertCommentData *data, gconstpointer service) { set_up_comment ((CommentData*) data, service); gdata_test_mock_server_start_trace (mock_server, "setup-insert-comment"); /* Create a test comment to be inserted. */ data->comment = gdata_youtube_comment_new (NULL); g_assert (GDATA_IS_YOUTUBE_COMMENT (data->comment)); gdata_entry_set_content (GDATA_ENTRY (data->comment), "This is a test comment."); uhm_server_end_trace (mock_server); } static void tear_down_insert_comment (InsertCommentData *data, gconstpointer service) { gdata_test_mock_server_start_trace (mock_server, "teardown-insert-comment"); if (data->comment != NULL) { g_object_unref (data->comment); } tear_down_comment ((CommentData*) data, service); uhm_server_end_trace (mock_server); } static void assert_comments_equal (GDataComment *new_comment, GDataYouTubeComment *original_comment, gboolean allow_empty) { GList *authors; GDataAuthor *author; g_assert (GDATA_IS_YOUTUBE_COMMENT (new_comment)); g_assert (GDATA_IS_YOUTUBE_COMMENT (original_comment)); g_assert (GDATA_YOUTUBE_COMMENT (new_comment) != original_comment); /* Comments can be "" if they’ve just been inserted and are pending * moderation. Not much we can do about that without waiting a few * minutes, which would suck in a unit test. */ if (g_strcmp0 (gdata_entry_get_content (GDATA_ENTRY (new_comment)), "") != 0) { g_assert_cmpstr (gdata_entry_get_content (GDATA_ENTRY (new_comment)), ==, gdata_entry_get_content (GDATA_ENTRY (original_comment))); } else { g_assert (allow_empty); } g_assert_cmpstr (gdata_youtube_comment_get_parent_comment_uri (GDATA_YOUTUBE_COMMENT (new_comment)), ==, gdata_youtube_comment_get_parent_comment_uri (original_comment)); /* Check the author of the new comment. */ authors = gdata_entry_get_authors (GDATA_ENTRY (new_comment)); g_assert_cmpuint (g_list_length (authors), ==, 1); author = GDATA_AUTHOR (authors->data); g_assert_cmpstr (gdata_author_get_name (author), ==, "GDataTest"); g_assert_cmpstr (gdata_author_get_uri (author), ==, "http://www.youtube.com/user/GDataTest"); } static void test_comment_insert (InsertCommentData *data, gconstpointer service) { GDataComment *new_comment; GError *error = NULL; gdata_test_mock_server_start_trace (mock_server, "comment-insert"); new_comment = gdata_commentable_insert_comment (GDATA_COMMENTABLE (data->parent.video), GDATA_SERVICE (service), GDATA_COMMENT (data->comment), NULL, &error); g_assert_no_error (error); g_clear_error (&error); assert_comments_equal (new_comment, data->comment, TRUE); g_object_unref (new_comment); uhm_server_end_trace (mock_server); } GDATA_ASYNC_CLOSURE_FUNCTIONS (insert_comment, InsertCommentData); GDATA_ASYNC_TEST_FUNCTIONS (comment_insert, InsertCommentData, G_STMT_START { gdata_commentable_insert_comment_async (GDATA_COMMENTABLE (data->parent.video), GDATA_SERVICE (service), GDATA_COMMENT (data->comment), cancellable, async_ready_callback, async_data); } G_STMT_END, G_STMT_START { GDataComment *new_comment; new_comment = gdata_commentable_insert_comment_finish (GDATA_COMMENTABLE (obj), async_result, &error); if (error == NULL) { assert_comments_equal (new_comment, data->comment, TRUE); g_object_unref (new_comment); } else { g_assert (new_comment == NULL); } } G_STMT_END); static void test_comment_delete (InsertCommentData *data, gconstpointer service) { gboolean success; GError *error = NULL; gdata_test_mock_server_start_trace (mock_server, "comment-delete"); /* We attempt to delete a comment which hasn't been inserted here, but that doesn't matter as the function should always immediately * return an error because deleting YouTube comments isn't allowed. */ success = gdata_commentable_delete_comment (GDATA_COMMENTABLE (data->parent.video), GDATA_SERVICE (service), GDATA_COMMENT (data->comment), NULL, &error); g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_FORBIDDEN); g_assert (success == FALSE); g_clear_error (&error); uhm_server_end_trace (mock_server); } GDATA_ASYNC_TEST_FUNCTIONS (comment_delete, InsertCommentData, G_STMT_START { gdata_commentable_delete_comment_async (GDATA_COMMENTABLE (data->parent.video), GDATA_SERVICE (service), GDATA_COMMENT (data->comment), cancellable, async_ready_callback, async_data); } G_STMT_END, G_STMT_START { gboolean success; success = gdata_commentable_delete_comment_finish (GDATA_COMMENTABLE (obj), async_result, &error); g_assert (error != NULL); g_assert (success == FALSE); /* See the note above in test_comment_delete(). */ if (g_error_matches (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_FORBIDDEN) == TRUE) { /* Pretend no error happened so that the test succeeds. */ g_clear_error (&error); async_data->cancellation_timeout = 13; } } G_STMT_END); static void test_parsing_video_id_from_uri (void) { gchar *video_id; video_id = gdata_youtube_video_get_video_id_from_uri ("http://www.youtube.com/watch?v=BH_vwsyCrTc&feature=featured"); g_assert_cmpstr (video_id, ==, "BH_vwsyCrTc"); g_free (video_id); video_id = gdata_youtube_video_get_video_id_from_uri ("http://www.youtube.es/watch?v=foo"); g_assert_cmpstr (video_id, ==, "foo"); g_free (video_id); video_id = gdata_youtube_video_get_video_id_from_uri ("http://foobar.com/watch?v=foo"); g_assert (video_id == NULL); video_id = gdata_youtube_video_get_video_id_from_uri ("http://foobar.com/not/real"); g_assert (video_id == NULL); video_id = gdata_youtube_video_get_video_id_from_uri ("http://www.youtube.com/watch#!v=ylLzyHk54Z0"); g_assert_cmpstr (video_id, ==, "ylLzyHk54Z0"); g_free (video_id); video_id = gdata_youtube_video_get_video_id_from_uri ("http://www.youtube.com/watch#!foo=bar!v=ylLzyHk54Z0"); g_assert_cmpstr (video_id, ==, "ylLzyHk54Z0"); g_free (video_id); video_id = gdata_youtube_video_get_video_id_from_uri ("http://www.youtube.com/watch#!foo=bar"); g_assert (video_id == NULL); video_id = gdata_youtube_video_get_video_id_from_uri ("http://www.youtube.com/watch#random-fragment"); g_assert (video_id == NULL); } static void test_categories (gconstpointer service) { GDataAPPCategories *app_categories; GList *categories; GError *error = NULL; gchar *old_locale; guint old_n_results; gdata_test_mock_server_start_trace (mock_server, "categories"); app_categories = gdata_youtube_service_get_categories (GDATA_YOUTUBE_SERVICE (service), NULL, &error); g_assert_no_error (error); g_assert (GDATA_IS_APP_CATEGORIES (app_categories)); g_clear_error (&error); categories = gdata_app_categories_get_categories (app_categories); g_assert_cmpint (g_list_length (categories), >, 0); g_assert (GDATA_IS_YOUTUBE_CATEGORY (categories->data)); /* Save the number of results for comparison against a different locale */ old_n_results = g_list_length (categories); g_object_unref (app_categories); /* Test with a different locale */ old_locale = g_strdup (gdata_service_get_locale (GDATA_SERVICE (service))); gdata_service_set_locale (GDATA_SERVICE (service), "TR"); app_categories = gdata_youtube_service_get_categories (GDATA_YOUTUBE_SERVICE (service), NULL, &error); g_assert_no_error (error); g_assert (GDATA_IS_APP_CATEGORIES (app_categories)); g_clear_error (&error); categories = gdata_app_categories_get_categories (app_categories); g_assert_cmpint (g_list_length (categories), >, 0); g_assert (GDATA_IS_YOUTUBE_CATEGORY (categories->data)); /* Compare the number of results */ g_assert_cmpuint (old_n_results, !=, g_list_length (categories)); g_object_unref (app_categories); /* Reset the locale */ gdata_service_set_locale (GDATA_SERVICE (service), old_locale); g_free (old_locale); uhm_server_end_trace (mock_server); } GDATA_ASYNC_TEST_FUNCTIONS (categories, void, G_STMT_START { gdata_youtube_service_get_categories_async (GDATA_YOUTUBE_SERVICE (service), cancellable, async_ready_callback, async_data); } G_STMT_END, G_STMT_START { GDataAPPCategories *app_categories; GList *categories; app_categories = gdata_youtube_service_get_categories_finish (GDATA_YOUTUBE_SERVICE (obj), async_result, &error); if (error == NULL) { g_assert (GDATA_IS_APP_CATEGORIES (app_categories)); categories = gdata_app_categories_get_categories (app_categories); g_assert_cmpint (g_list_length (categories), >, 0); g_assert (GDATA_IS_YOUTUBE_CATEGORY (categories->data)); g_object_unref (app_categories); } else { g_assert (app_categories == NULL); } } G_STMT_END); typedef struct { GDataEntry *new_video; GDataEntry *new_video2; } BatchData; static void setup_batch (BatchData *data, gconstpointer service) { GDataEntry *video; GError *error = NULL; gdata_test_mock_server_start_trace (mock_server, "setup-batch"); /* We can't insert new videos as they'd just hit the moderation queue and cause tests to fail. Instead, we rely on two videos already existing * on the server with the given IDs. */ video = gdata_service_query_single_entry (GDATA_SERVICE (service), gdata_youtube_service_get_primary_authorization_domain (), "tag:youtube.com,2008:video:RzR2k8yo4NY", NULL, GDATA_TYPE_YOUTUBE_VIDEO, NULL, &error); g_assert_no_error (error); g_assert (GDATA_IS_YOUTUBE_VIDEO (video)); data->new_video = video; video = gdata_service_query_single_entry (GDATA_SERVICE (service), gdata_youtube_service_get_primary_authorization_domain (), "tag:youtube.com,2008:video:VppEcVz8qaI", NULL, GDATA_TYPE_YOUTUBE_VIDEO, NULL, &error); g_assert_no_error (error); g_assert (GDATA_IS_YOUTUBE_VIDEO (video)); data->new_video2 = video; uhm_server_end_trace (mock_server); } static void test_batch (BatchData *data, gconstpointer service) { GDataBatchOperation *operation; GDataService *service2; gchar *feed_uri; guint op_id, op_id2; GError *error = NULL; gdata_test_mock_server_start_trace (mock_server, "batch"); /* Here we hardcode the feed URI, but it should really be extracted from a video feed, as the GDATA_LINK_BATCH link. * It looks like this feed is read-only, so we can only test querying. */ operation = gdata_batchable_create_operation (GDATA_BATCHABLE (service), gdata_youtube_service_get_primary_authorization_domain (), "https://gdata.youtube.com/feeds/api/videos/batch"); /* Check the properties of the operation */ g_assert (gdata_batch_operation_get_service (operation) == service); g_assert_cmpstr (gdata_batch_operation_get_feed_uri (operation), ==, "https://gdata.youtube.com/feeds/api/videos/batch"); g_object_get (operation, "service", &service2, "feed-uri", &feed_uri, NULL); g_assert (service2 == service); g_assert_cmpstr (feed_uri, ==, "https://gdata.youtube.com/feeds/api/videos/batch"); g_object_unref (service2); g_free (feed_uri); /* Run a singleton batch operation to query one of the entries. This * should now always fail, as batch operations were deprecated by v3 * of the YouTube API. */ gdata_test_batch_operation_query (operation, gdata_entry_get_id (data->new_video), GDATA_TYPE_YOUTUBE_VIDEO, data->new_video, NULL, NULL); g_assert (!gdata_batch_operation_run (operation, NULL, &error)); g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_WITH_BATCH_OPERATION); g_clear_error (&error); g_object_unref (operation); /* Run another batch operation to query the two entries */ operation = gdata_batchable_create_operation (GDATA_BATCHABLE (service), gdata_youtube_service_get_primary_authorization_domain (), "https://gdata.youtube.com/feeds/api/videos/batch"); op_id = gdata_test_batch_operation_query (operation, gdata_entry_get_id (data->new_video), GDATA_TYPE_YOUTUBE_VIDEO, data->new_video, NULL, NULL); op_id2 = gdata_test_batch_operation_query (operation, gdata_entry_get_id (data->new_video2), GDATA_TYPE_YOUTUBE_VIDEO, data->new_video2, NULL, NULL); g_assert_cmpuint (op_id, !=, op_id2); g_assert (!gdata_batch_operation_run (operation, NULL, &error)); g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_WITH_BATCH_OPERATION); g_clear_error (&error); g_object_unref (operation); uhm_server_end_trace (mock_server); } static void test_batch_async_cb (GDataBatchOperation *operation, GAsyncResult *async_result, GMainLoop *main_loop) { GError *error = NULL; g_assert (!gdata_batch_operation_run_finish (operation, async_result, &error)); g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_WITH_BATCH_OPERATION); g_clear_error (&error); g_main_loop_quit (main_loop); } static void test_batch_async (BatchData *data, gconstpointer service) { GDataBatchOperation *operation; GMainLoop *main_loop; GError *error = NULL; gdata_test_mock_server_start_trace (mock_server, "batch-async"); /* Run an async query operation on the video */ operation = gdata_batchable_create_operation (GDATA_BATCHABLE (service), gdata_youtube_service_get_primary_authorization_domain (), "https://gdata.youtube.com/feeds/api/videos/batch"); gdata_test_batch_operation_query (operation, gdata_entry_get_id (data->new_video), GDATA_TYPE_YOUTUBE_VIDEO, data->new_video, NULL, &error); main_loop = g_main_loop_new (NULL, TRUE); gdata_batch_operation_run_async (operation, NULL, (GAsyncReadyCallback) test_batch_async_cb, main_loop); g_main_loop_run (main_loop); g_main_loop_unref (main_loop); g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_WITH_BATCH_OPERATION); g_clear_error (&error); uhm_server_end_trace (mock_server); } static void test_batch_async_cancellation_cb (GDataBatchOperation *operation, GAsyncResult *async_result, GMainLoop *main_loop) { GError *error = NULL; g_assert (gdata_batch_operation_run_finish (operation, async_result, &error) == FALSE); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); g_clear_error (&error); g_main_loop_quit (main_loop); } static void test_batch_async_cancellation (BatchData *data, gconstpointer service) { GDataBatchOperation *operation; GMainLoop *main_loop; GCancellable *cancellable; GError *error = NULL; gdata_test_mock_server_start_trace (mock_server, "batch-async-cancellation"); /* Run an async query operation on the video */ operation = gdata_batchable_create_operation (GDATA_BATCHABLE (service), gdata_youtube_service_get_primary_authorization_domain (), "https://gdata.youtube.com/feeds/api/videos/batch"); gdata_test_batch_operation_query (operation, gdata_entry_get_id (data->new_video), GDATA_TYPE_YOUTUBE_VIDEO, data->new_video, NULL, &error); main_loop = g_main_loop_new (NULL, TRUE); cancellable = g_cancellable_new (); gdata_batch_operation_run_async (operation, cancellable, (GAsyncReadyCallback) test_batch_async_cancellation_cb, main_loop); g_cancellable_cancel (cancellable); /* this should cancel the operation before it even starts, as we haven't run the main loop yet */ g_main_loop_run (main_loop); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); g_clear_error (&error); g_main_loop_unref (main_loop); g_object_unref (cancellable); g_object_unref (operation); uhm_server_end_trace (mock_server); } static void teardown_batch (BatchData *data, gconstpointer service) { g_object_unref (data->new_video); g_object_unref (data->new_video2); } static void mock_server_notify_resolver_cb (GObject *object, GParamSpec *pspec, gpointer user_data) { UhmServer *server; UhmResolver *resolver; server = UHM_SERVER (object); /* Set up the expected domain names here. This should technically be split up between * the different unit test suites, but that's too much effort. */ resolver = uhm_server_get_resolver (server); if (resolver != NULL) { const gchar *ip_address = uhm_server_get_address (server); uhm_resolver_add_A (resolver, "www.google.com", ip_address); uhm_resolver_add_A (resolver, "www.googleapis.com", ip_address); uhm_resolver_add_A (resolver, "accounts.google.com", ip_address); } } /* Set up a global GDataAuthorizer to be used for all the tests. Unfortunately, * the YouTube API is limited to OAuth2 authorisation, so this requires user * interaction when online. * * If not online, use a dummy authoriser. */ static GDataAuthorizer * create_global_authorizer (void) { GDataOAuth2Authorizer *authorizer = NULL; /* owned */ gchar *authentication_uri, *authorisation_code; GError *error = NULL; /* If not online, just return a dummy authoriser. */ if (!uhm_server_get_enable_online (mock_server)) { return GDATA_AUTHORIZER (gdata_dummy_authorizer_new (GDATA_TYPE_YOUTUBE_SERVICE)); } /* Otherwise, go through the interactive OAuth dance. */ gdata_test_mock_server_start_trace (mock_server, "global-authentication"); authorizer = gdata_oauth2_authorizer_new (CLIENT_ID, CLIENT_SECRET, REDIRECT_URI, GDATA_TYPE_YOUTUBE_SERVICE); /* Get an authentication URI */ authentication_uri = gdata_oauth2_authorizer_build_authentication_uri (authorizer, NULL, FALSE); g_assert (authentication_uri != NULL); /* Get the authorisation code off the user. */ authorisation_code = gdata_test_query_user_for_verifier (authentication_uri); g_free (authentication_uri); if (authorisation_code == NULL) { /* Skip tests. */ g_object_unref (authorizer); authorizer = NULL; goto skip_test; } /* Authorise the token */ g_assert (gdata_oauth2_authorizer_request_authorization (authorizer, authorisation_code, NULL, &error)); g_assert_no_error (error); skip_test: g_free (authorisation_code); uhm_server_end_trace (mock_server); return GDATA_AUTHORIZER (authorizer); } int main (int argc, char *argv[]) { gint retval; GDataAuthorizer *authorizer = NULL; /* owned */ GDataService *service = NULL; /* owned */ GFile *trace_directory = NULL; /* owned */ gchar *path = NULL; gdata_test_init (argc, argv); mock_server = gdata_test_get_mock_server (); g_signal_connect (G_OBJECT (mock_server), "notify::resolver", (GCallback) mock_server_notify_resolver_cb, NULL); path = g_test_build_filename (G_TEST_DIST, "traces/youtube", NULL); trace_directory = g_file_new_for_path (path); g_free (path); uhm_server_set_trace_directory (mock_server, trace_directory); g_object_unref (trace_directory); authorizer = create_global_authorizer (); service = GDATA_SERVICE (gdata_youtube_service_new (DEVELOPER_KEY, authorizer)); g_test_add_func ("/youtube/authentication", test_authentication); g_test_add_data_func ("/youtube/query/standard_feeds", service, test_query_standard_feeds); g_test_add_data_func ("/youtube/query/standard_feed", service, test_query_standard_feed); g_test_add_data_func ("/youtube/query/standard_feed/with_query", service, test_query_standard_feed_with_query); g_test_add_data_func ("/youtube/query/standard_feed/error", service, test_query_standard_feed_error); g_test_add_data_func ("/youtube/query/standard_feed/timeout", service, test_query_standard_feed_timeout); g_test_add ("/youtube/query/standard_feed/async", StandardFeedData, service, set_up_standard_feed_async, (void (*)(StandardFeedData *, const void *)) test_query_standard_feed_async, tear_down_standard_feed_async); g_test_add_data_func ("/youtube/query/standard_feed/async/progress_closure", service, test_query_standard_feed_async_progress_closure); g_test_add ("/youtube/query/standard_feed/async/cancellation", StandardFeedData, service, set_up_standard_feed_async, (void (*)(StandardFeedData *, const void *)) test_query_standard_feed_async_cancellation, tear_down_standard_feed_async); g_test_add_data_func ("/youtube/query/related", service, test_query_related); g_test_add ("/youtube/query/related/async", GDataAsyncTestData, service, gdata_set_up_async_test_data, test_query_related_async, gdata_tear_down_async_test_data); g_test_add_data_func ("/youtube/query/related/async/progress_closure", service, test_query_related_async_progress_closure); g_test_add ("/youtube/query/related/async/cancellation", GDataAsyncTestData, service, gdata_set_up_async_test_data, test_query_related_async_cancellation, gdata_tear_down_async_test_data); g_test_add ("/youtube/upload/simple", UploadData, service, set_up_upload, test_upload_simple, tear_down_upload); g_test_add ("/youtube/upload/async", GDataAsyncTestData, service, set_up_upload_async, test_upload_async, tear_down_upload_async); g_test_add ("/youtube/upload/async/cancellation", GDataAsyncTestData, service, set_up_upload_async, test_upload_async_cancellation, tear_down_upload_async); g_test_add_data_func ("/youtube/query/single", service, test_query_single); g_test_add ("/youtube/query/single/async", GDataAsyncTestData, service, gdata_set_up_async_test_data, test_query_single_async, gdata_tear_down_async_test_data); g_test_add ("/youtube/query/single/async/cancellation", GDataAsyncTestData, service, gdata_set_up_async_test_data, test_query_single_async_cancellation, gdata_tear_down_async_test_data); g_test_add ("/youtube/comment/query", CommentData, service, set_up_comment, test_comment_query, tear_down_comment); g_test_add ("/youtube/comment/query/async", GDataAsyncTestData, service, set_up_comment_async, test_comment_query_async, tear_down_comment_async); g_test_add ("/youtube/comment/query/async/cancellation", GDataAsyncTestData, service, set_up_comment_async, test_comment_query_async_cancellation, tear_down_comment_async); g_test_add ("/youtube/comment/query/async/progress_closure", CommentData, service, set_up_comment, test_comment_query_async_progress_closure, tear_down_comment); g_test_add ("/youtube/comment/insert", InsertCommentData, service, set_up_insert_comment, test_comment_insert, tear_down_insert_comment); g_test_add ("/youtube/comment/insert/async", GDataAsyncTestData, service, set_up_insert_comment_async, test_comment_insert_async, tear_down_insert_comment_async); g_test_add ("/youtube/comment/insert/async/cancellation", GDataAsyncTestData, service, set_up_insert_comment_async, test_comment_insert_async_cancellation, tear_down_insert_comment_async); g_test_add ("/youtube/comment/delete", InsertCommentData, service, set_up_insert_comment, test_comment_delete, tear_down_insert_comment); g_test_add ("/youtube/comment/delete/async", GDataAsyncTestData, service, set_up_insert_comment_async, test_comment_delete_async, tear_down_insert_comment_async); g_test_add ("/youtube/comment/delete/async/cancellation", GDataAsyncTestData, service, set_up_insert_comment_async, test_comment_delete_async_cancellation, tear_down_insert_comment_async); g_test_add_data_func ("/youtube/categories", service, test_categories); g_test_add ("/youtube/categories/async", GDataAsyncTestData, service, gdata_set_up_async_test_data, test_categories_async, gdata_tear_down_async_test_data); g_test_add ("/youtube/categories/async/cancellation", GDataAsyncTestData, service, gdata_set_up_async_test_data, test_categories_async_cancellation, gdata_tear_down_async_test_data); g_test_add ("/youtube/batch", BatchData, service, setup_batch, test_batch, teardown_batch); g_test_add ("/youtube/batch/async", BatchData, service, setup_batch, test_batch_async, teardown_batch); g_test_add ("/youtube/batch/async/cancellation", BatchData, service, setup_batch, test_batch_async_cancellation, teardown_batch); g_test_add_func ("/youtube/service/properties", test_service_properties); g_test_add_func ("/youtube/parsing/app:control", test_parsing_app_control); g_test_add_func ("/youtube/parsing/yt:recorded", test_parsing_yt_recorded); g_test_add_func ("/youtube/parsing/yt:accessControl", test_parsing_yt_access_control); g_test_add_func ("/youtube/parsing/yt:category", test_parsing_yt_category); g_test_add_func ("/youtube/parsing/video_id_from_uri", test_parsing_video_id_from_uri); g_test_add_func ("/youtube/parsing/georss:where", test_parsing_georss_where); g_test_add_func ("/youtube/parsing/ratings", test_parsing_ratings); g_test_add_func ("/youtube/video/escaping", test_video_escaping); g_test_add_func ("/youtube/video/location", test_video_location); g_test_add_func ("/youtube/comment/get_json", test_comment_get_json); g_test_add_func ("/youtube/comment/properties/parent-comment-id", test_comment_properties_parent_comment_uri); g_test_add_func ("/youtube/query/uri", test_query_uri); g_test_add_func ("/youtube/query/etag", test_query_etag); retval = g_test_run (); g_clear_object (&service); g_clear_object (&authorizer); return retval; }