1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3  * GData Client
4  * Copyright (C) Philip Withnall 2008–2010 <philip@tecnocode.co.uk>
5  *
6  * GData Client is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * GData Client is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with GData Client.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <glib.h>
21 #include <locale.h>
22 
23 #include "gdata.h"
24 #include "common.h"
25 
26 static void
test_documents_property_parse_json(void)27 test_documents_property_parse_json (void)
28 {
29 	GDataDocumentsProperty *property;
30 	GError *error = NULL;
31 
32 	/* Create an entry from JSON with unhandled nodes. */
33 	property = GDATA_DOCUMENTS_PROPERTY (gdata_parsable_new_from_json (GDATA_TYPE_DOCUMENTS_PROPERTY,
34 									 "{"
35 									 "\"key\":\"foobar\","
36 									 "\"etag\":\"some-etag\","
37 									 "\"value\":\"some foobar value\","
38 									 "\"visibility\":\"PUBLIC\","
39 									 "\"unhandled-boolean\":false,"
40 									 "\"unhandled-string\":\"this-is-a-string---sometimes\","
41 									 "\"unhandled-int\":15,"
42 									 "\"unhandled-double\":42.42,"
43 									 "\"unhandled-object\":{"
44 									 "\"a\":true,"
45 									 "\"b\":true"
46 									 "},"
47 									 "\"unhandled-array\":["
48 									 "1,"
49 									 "2,"
50 									 "3"
51 									 "],"
52 									 "\"unhandled-null\":null"
53 									 "}", -1, &error));
54 	g_assert_no_error (error);
55 	g_assert (GDATA_IS_DOCUMENTS_PROPERTY (property));
56 
57 	/* Now check the outputted JSON from the property still has the unhandled nodes. */
58 	gdata_test_assert_json (property,
59 				"{"
60 				"\"key\":\"foobar\","
61 				"\"etag\":\"some-etag\","
62 				"\"value\":\"some foobar value\","
63 				"\"visibility\":\"PUBLIC\","
64 				"\"unhandled-boolean\":false,"
65 				"\"unhandled-string\":\"this-is-a-string---sometimes\","
66 				"\"unhandled-int\":15,"
67 				"\"unhandled-double\":42.42,"
68 				"\"unhandled-object\":{"
69 				"\"a\":true,"
70 				"\"b\":true"
71 				"},"
72 				"\"unhandled-array\":["
73 				"1,"
74 				"2,"
75 				"3"
76 				"],"
77 				"\"unhandled-null\":null"
78 				"}");
79 	g_object_unref (property);
80 }
81 
82 static void
test_documents_property_get_json(void)83 test_documents_property_get_json (void)
84 {
85 	GDataDocumentsProperty *property1, *property2;
86 	gchar *json;
87 	GError *error = NULL;
88 
89 	property1 = gdata_documents_property_new ("Testing key & \"escaping\"");
90 
91 	/* Set the properties more conventionally */
92 	gdata_documents_property_set_value (property1, "Testing value & \"escaping\"");
93 	gdata_documents_property_set_visibility (property1, GDATA_DOCUMENTS_PROPERTY_VISIBILITY_PRIVATE);
94 
95 	/* Check the generated JSON's OK */
96 	gdata_test_assert_json (property1,
97 				"{"
98 				"\"key\":\"Testing key & \\\"escaping\\\"\","
99 				"\"value\":\"Testing value & \\\"escaping\\\"\","
100 				"\"visibility\":\"PRIVATE\""
101 				"}");
102 
103 	/* Check again by re-parsing the JSON to a GDataEntry. */
104 	json = gdata_parsable_get_json (GDATA_PARSABLE (property1));
105 	property2 = GDATA_DOCUMENTS_PROPERTY (gdata_parsable_new_from_json (GDATA_TYPE_DOCUMENTS_PROPERTY, json, -1, &error));
106 	g_assert_no_error (error);
107 	g_assert (GDATA_IS_DOCUMENTS_PROPERTY (property2));
108 	g_clear_error (&error);
109 	g_free (json);
110 
111 	g_assert_cmpstr (gdata_documents_property_get_key (property1), ==, gdata_documents_property_get_key (property2));
112 	g_assert_cmpstr (gdata_documents_property_get_etag (property1), ==, gdata_documents_property_get_etag (property2));
113 	g_assert_cmpstr (gdata_documents_property_get_value (property1), ==, gdata_documents_property_get_value (property2));
114 	g_assert_cmpstr (gdata_documents_property_get_visibility (property1), ==, gdata_documents_property_get_visibility (property2));
115 
116 	g_object_unref (property1);
117 	g_object_unref (property2);
118 }
119 
120 static void
test_xml_comparison(void)121 test_xml_comparison (void)
122 {
123 	GDataAccessRule *rule;
124 
125 	/* Since we've written the XML comparison function used across all the test suites, it's necessary to test that it actually works before we
126 	 * blindly assert that its results are correct. */
127 	rule = gdata_access_rule_new ("an-id");
128 	gdata_access_rule_set_role (rule, GDATA_ACCESS_ROLE_NONE);
129 	gdata_access_rule_set_scope (rule, GDATA_ACCESS_SCOPE_USER, "foo@example.com");
130 
131 	/* Check a valid comparison */
132 	gdata_test_assert_xml (rule,
133 		"<?xml version='1.0' encoding='UTF-8'?>"
134 		"<entry xmlns='http://www.w3.org/2005/Atom' "
135 		       "xmlns:gd='http://schemas.google.com/g/2005' "
136 		       "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
137 			"<title type='text'>none</title>"
138 			"<id>an-id</id>"
139 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
140 			"<gAcl:role value='none'/>"
141 			"<gAcl:scope type='user' value='foo@example.com'/>"
142 		"</entry>");
143 
144 	/* Check a valid comparison with namespaces swapped */
145 	gdata_test_assert_xml (rule,
146 		"<?xml version='1.0' encoding='UTF-8'?>"
147 		"<entry xmlns='http://www.w3.org/2005/Atom' "
148 		       "xmlns:gAcl='http://schemas.google.com/acl/2007' "
149 		       "xmlns:gd='http://schemas.google.com/g/2005'>"
150 			"<title type='text'>none</title>"
151 			"<id>an-id</id>"
152 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
153 			"<gAcl:role value='none'/>"
154 			"<gAcl:scope type='user' value='foo@example.com'/>"
155 		"</entry>");
156 
157 	/* Check a valid comparison with elements swapped */
158 	gdata_test_assert_xml (rule,
159 		"<?xml version='1.0' encoding='UTF-8'?>"
160 		"<entry xmlns='http://www.w3.org/2005/Atom' "
161 		       "xmlns:gd='http://schemas.google.com/g/2005' "
162 		       "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
163 			"<id>an-id</id>"
164 			"<title type='text'>none</title>"
165 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
166 			"<gAcl:role value='none'/>"
167 			"<gAcl:scope type='user' value='foo@example.com'/>"
168 		"</entry>");
169 
170 	/* Missing namespace (still valid XML, just not what's expected) */
171 	g_assert (gdata_test_compare_xml (GDATA_PARSABLE (rule),
172 		"<?xml version='1.0' encoding='UTF-8'?>"
173 		"<entry xmlns='http://www.w3.org/2005/Atom' "
174 		       "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
175 			"<title type='text'>none</title>"
176 			"<id>an-id</id>"
177 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
178 			"<gAcl:role value='none'/>"
179 			"<gAcl:scope type='user' value='foo@example.com'/>"
180 		"</entry>", FALSE) == FALSE);
181 
182 	/* Extra namespace */
183 	g_assert (gdata_test_compare_xml (GDATA_PARSABLE (rule),
184 		"<?xml version='1.0' encoding='UTF-8'?>"
185 		"<entry xmlns='http://www.w3.org/2005/Atom' "
186 		       "xmlns:gd='http://schemas.google.com/g/2005' "
187 		       "xmlns:gAcl='http://schemas.google.com/acl/2007' "
188 		       "xmlns:foo='http://foo.com/'>"
189 			"<title type='text'>none</title>"
190 			"<id>an-id</id>"
191 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
192 			"<gAcl:role value='none'/>"
193 			"<gAcl:scope type='user' value='foo@example.com'/>"
194 		"</entry>", FALSE) == FALSE);
195 
196 	/* Missing element */
197 	g_assert (gdata_test_compare_xml (GDATA_PARSABLE (rule),
198 		"<?xml version='1.0' encoding='UTF-8'?>"
199 		"<entry xmlns='http://www.w3.org/2005/Atom' "
200 		       "xmlns:gd='http://schemas.google.com/g/2005' "
201 		       "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
202 			"<id>an-id</id>"
203 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
204 			"<gAcl:role value='none'/>"
205 			"<gAcl:scope type='user' value='foo@example.com'/>"
206 		"</entry>", FALSE) == FALSE);
207 
208 	/* Extra element */
209 	g_assert (gdata_test_compare_xml (GDATA_PARSABLE (rule),
210 		"<?xml version='1.0' encoding='UTF-8'?>"
211 		"<entry xmlns='http://www.w3.org/2005/Atom' "
212 		       "xmlns:gd='http://schemas.google.com/g/2005' "
213 		       "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
214 			"<title type='text'>none</title>"
215 			"<foo>bar</foo>"
216 			"<id>an-id</id>"
217 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
218 			"<gAcl:role value='none'/>"
219 			"<gAcl:scope type='user' value='foo@example.com'/>"
220 		"</entry>", FALSE) == FALSE);
221 
222 	/* Incorrect namespace on element */
223 	g_assert (gdata_test_compare_xml (GDATA_PARSABLE (rule),
224 		"<?xml version='1.0' encoding='UTF-8'?>"
225 		"<entry xmlns='http://www.w3.org/2005/Atom' "
226 		       "xmlns:gd='http://schemas.google.com/g/2005' "
227 		       "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
228 			"<gAcl:title type='text'>none</gAcl:title>"
229 			"<id>an-id</id>"
230 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
231 			"<gAcl:role value='none'/>"
232 			"<gAcl:scope type='user' value='foo@example.com'/>"
233 		"</entry>", FALSE) == FALSE);
234 
235 	/* Mis-valued content */
236 	g_assert (gdata_test_compare_xml (GDATA_PARSABLE (rule),
237 		"<?xml version='1.0' encoding='UTF-8'?>"
238 		"<entry xmlns='http://www.w3.org/2005/Atom' "
239 		       "xmlns:gd='http://schemas.google.com/g/2005' "
240 		       "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
241 			"<title type='text'>none</title>"
242 			"<id>an-other-id</id>"
243 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
244 			"<gAcl:role value='none'/>"
245 			"<gAcl:scope type='user' value='foo@example.com'/>"
246 		"</entry>", FALSE) == FALSE);
247 
248 	/* Missing attribute */
249 	g_assert (gdata_test_compare_xml (GDATA_PARSABLE (rule),
250 		"<?xml version='1.0' encoding='UTF-8'?>"
251 		"<entry xmlns='http://www.w3.org/2005/Atom' "
252 		       "xmlns:gd='http://schemas.google.com/g/2005' "
253 		       "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
254 			"<title type='text'>none</title>"
255 			"<id>an-id</id>"
256 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
257 			"<gAcl:role/>"
258 			"<gAcl:scope type='user' value='foo@example.com'/>"
259 		"</entry>", FALSE) == FALSE);
260 
261 	/* Extra attribute */
262 	g_assert (gdata_test_compare_xml (GDATA_PARSABLE (rule),
263 		"<?xml version='1.0' encoding='UTF-8'?>"
264 		"<entry xmlns='http://www.w3.org/2005/Atom' "
265 		       "xmlns:gd='http://schemas.google.com/g/2005' "
266 		       "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
267 			"<title type='text'>none</title>"
268 			"<id>an-id</id>"
269 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
270 			"<gAcl:role value='none' other-value='foo'/>"
271 			"<gAcl:scope type='user' value='foo@example.com'/>"
272 		"</entry>", FALSE) == FALSE);
273 
274 	/* Mis-valued attribute */
275 	g_assert (gdata_test_compare_xml (GDATA_PARSABLE (rule),
276 		"<?xml version='1.0' encoding='UTF-8'?>"
277 		"<entry xmlns='http://www.w3.org/2005/Atom' "
278 		       "xmlns:gd='http://schemas.google.com/g/2005' "
279 		       "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
280 			"<title type='text'>none</title>"
281 			"<id>an-id</id>"
282 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
283 			"<gAcl:role value='other'/>"
284 			"<gAcl:scope type='user' value='foo@example.com'/>"
285 		"</entry>", FALSE) == FALSE);
286 
287 	g_object_unref (rule);
288 }
289 
290 static void
test_entry_get_xml(void)291 test_entry_get_xml (void)
292 {
293 	gint64 updated, published, updated2, published2, updated3, published3;
294 	GDataEntry *entry, *entry2;
295 	GDataCategory *category;
296 	GDataLink *_link; /* stupid unistd.h */
297 	GDataAuthor *author;
298 	gchar *xml, *title, *summary, *id, *etag, *content, *content_uri, *rights;
299 	gboolean is_inserted;
300 	GList *list;
301 	GError *error = NULL;
302 
303 	entry = gdata_entry_new (NULL);
304 
305 	/* Test setting properties directly */
306 	g_object_set (G_OBJECT (entry),
307 	              "title", "First testing title & escaping",
308 	              "summary", "Test summary & escaping.",
309 	              "content", "Test <markup> & escaping.",
310 	              "rights", "Philip Withnall <philip@tecnocode.co.uk>",
311 	              NULL);
312 
313 	g_assert_cmpstr (gdata_entry_get_title (entry), ==, "First testing title & escaping");
314 	g_assert_cmpstr (gdata_entry_get_summary (entry), ==, "Test summary & escaping.");
315 	g_assert_cmpstr (gdata_entry_get_content (entry), ==, "Test <markup> & escaping.");
316 	g_assert (gdata_entry_get_content_uri (entry) == NULL);
317 	g_assert_cmpstr (gdata_entry_get_rights (entry), ==, "Philip Withnall <philip@tecnocode.co.uk>");
318 
319 	/* Set the properties more conventionally */
320 	gdata_entry_set_title (entry, "Testing title & escaping");
321 	gdata_entry_set_summary (entry, NULL);
322 	gdata_entry_set_content (entry, "This is some sample content testing, amongst other things, <markup> & odd characters‽");
323 	gdata_entry_set_rights (entry, NULL);
324 
325 	/* Content URI */
326 	g_object_set (G_OBJECT (entry), "content-uri", "http://foo.com/", NULL);
327 
328 	g_assert (gdata_entry_get_content (entry) == NULL);
329 	g_assert_cmpstr (gdata_entry_get_content_uri (entry), ==, "http://foo.com/");
330 
331 	gdata_entry_set_content_uri (entry, "http://bar.com/");
332 
333 	/* Check the generated XML's OK */
334 	gdata_test_assert_xml (entry,
335 			 "<?xml version='1.0' encoding='UTF-8'?>"
336 			 "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005'>"
337 				 "<title type='text'>Testing title &amp; escaping</title>"
338 				 "<content type='text/plain' src='http://bar.com/'/>"
339 			 "</entry>");
340 
341 	/* Reset the content */
342 	gdata_entry_set_content (entry, "This is some sample content testing, amongst other things, <markup> & odd characters‽");
343 
344 	/* Categories */
345 	category = gdata_category_new ("test", NULL, NULL);
346 	gdata_entry_add_category (entry, category);
347 	g_object_unref (category);
348 	category = gdata_category_new ("example", NULL, "Example stuff");
349 	gdata_entry_add_category (entry, category);
350 	g_object_unref (category);
351 	category = gdata_category_new ("Film", "http://gdata.youtube.com/schemas/2007/categories.cat", "Film & Animation");
352 	gdata_entry_add_category (entry, category);
353 	g_object_unref (category);
354 
355 	/* Links */
356 	_link = gdata_link_new ("http://test.com/", GDATA_LINK_SELF);
357 	gdata_link_set_content_type (_link, "application/atom+xml");
358 	gdata_entry_add_link (entry, _link);
359 	g_object_unref (_link);
360 	_link = gdata_link_new ("http://example.com/", NULL);
361 	gdata_entry_add_link (entry, _link);
362 	g_object_unref (_link);
363 	_link = gdata_link_new ("http://test.mn/", GDATA_LINK_RELATED);
364 	gdata_link_set_content_type (_link, "text/html");
365 	gdata_link_set_language (_link, "mn");
366 	gdata_link_set_title (_link, "A treatise on Mongolian test websites & other stuff.");
367 	gdata_link_set_length (_link, 5010);
368 	gdata_entry_add_link (entry, _link);
369 	g_object_unref (_link);
370 	_link = gdata_link_new ("http://example.com/", "http://foobar.link");
371 	gdata_entry_add_link (entry, _link);
372 	g_object_unref (_link);
373 	_link = gdata_link_new ("http://example2.com/", "http://foobar.link");
374 	gdata_entry_add_link (entry, _link);
375 	g_object_unref (_link);
376 
377 	/* Authors */
378 	author = gdata_author_new ("Joe Bloggs", "http://example.com/", "joe@example.com");
379 	gdata_entry_add_author (entry, author);
380 	g_object_unref (author);
381 	author = gdata_author_new ("John Smith", NULL, "smith.john@example.com");
382 	gdata_entry_add_author (entry, author);
383 	g_object_unref (author);
384 	author = gdata_author_new ("F. Barr؟", NULL, NULL);
385 	gdata_entry_add_author (entry, author);
386 	g_object_unref (author);
387 
388 	/* Check the generated XML's OK */
389 	gdata_test_assert_xml (entry,
390 			 "<?xml version='1.0' encoding='UTF-8'?>"
391 			 "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005'>"
392 				 "<title type='text'>Testing title &amp; escaping</title>"
393 				 "<content type='text'>This is some sample content testing, amongst other things, &lt;markup&gt; &amp; odd characters\342\200\275</content>"
394 				 "<category term='Film' scheme='http://gdata.youtube.com/schemas/2007/categories.cat' label='Film &amp; Animation'/>"
395 				 "<category term='example' label='Example stuff'/>"
396 				 "<category term='test'/>"
397 				 "<link href='http://example2.com/' rel='http://foobar.link'/>"
398 				 "<link href='http://example.com/' rel='http://foobar.link'/>"
399 				 "<link href='http://test.mn/' title='A treatise on Mongolian test websites &amp; other stuff.' rel='http://www.iana.org/assignments/relation/related' type='text/html' hreflang='mn' length='5010'/>"
400 				 "<link href='http://example.com/' rel='http://www.iana.org/assignments/relation/alternate'/>"
401 				 "<link href='http://test.com/' rel='http://www.iana.org/assignments/relation/self' type='application/atom+xml'/>"
402 				 "<author><name>F. Barr\330\237</name></author>"
403 				 "<author><name>John Smith</name><email>smith.john@example.com</email></author>"
404 				 "<author><name>Joe Bloggs</name><uri>http://example.com/</uri><email>joe@example.com</email></author>"
405 			 "</entry>");
406 
407 	/* Check again by re-parsing the XML to a GDataEntry */
408 	xml = gdata_parsable_get_xml (GDATA_PARSABLE (entry));
409 	entry2 = GDATA_ENTRY (gdata_parsable_new_from_xml (GDATA_TYPE_ENTRY, xml, -1, &error));
410 	g_assert_no_error (error);
411 	g_assert (GDATA_IS_ENTRY (entry2));
412 	g_clear_error (&error);
413 	g_free (xml);
414 
415 	g_assert_cmpstr (gdata_entry_get_title (entry), ==, gdata_entry_get_title (entry2));
416 	g_assert_cmpstr (gdata_entry_get_id (entry), ==, gdata_entry_get_id (entry2)); /* should both be NULL */
417 	g_assert_cmpstr (gdata_entry_get_content (entry), ==, gdata_entry_get_content (entry2));
418 	g_assert_cmpstr (gdata_entry_get_content_uri (entry), ==, gdata_entry_get_content_uri (entry2)); /* should both be NULL */
419 
420 	updated = gdata_entry_get_updated (entry);
421 	updated2 = gdata_entry_get_updated (entry2);
422 	g_assert_cmpuint (updated, ==, updated2);
423 
424 	published = gdata_entry_get_published (entry);
425 	published2 = gdata_entry_get_published (entry2);
426 	g_assert_cmpuint (published, ==, published2);
427 
428 	/* Check links */
429 	_link = gdata_entry_look_up_link (entry, GDATA_LINK_SELF);
430 	g_assert (_link != NULL);
431 	g_assert_cmpstr (gdata_link_get_uri (_link), ==, "http://test.com/");
432 	g_assert_cmpstr (gdata_link_get_relation_type (_link), ==, GDATA_LINK_SELF);
433 	g_assert_cmpstr (gdata_link_get_content_type (_link), ==, "application/atom+xml");
434 
435 	_link = gdata_entry_look_up_link (entry, "http://link.not.exist");
436 	g_assert (_link == NULL);
437 
438 	list = gdata_entry_look_up_links (entry, "http://foobar.link");
439 	g_assert (list != NULL);
440 	g_assert_cmpint (g_list_length (list), ==, 2);
441 
442 	_link = GDATA_LINK (list->data);
443 	g_assert (_link != NULL);
444 	g_assert_cmpstr (gdata_link_get_uri (_link), ==, "http://example2.com/");
445 	g_assert_cmpstr (gdata_link_get_relation_type (_link), ==, "http://foobar.link");
446 
447 	_link = GDATA_LINK (list->next->data);
448 	g_assert (_link != NULL);
449 	g_assert_cmpstr (gdata_link_get_uri (_link), ==, "http://example.com/");
450 	g_assert_cmpstr (gdata_link_get_relation_type (_link), ==, "http://foobar.link");
451 
452 	g_list_free (list);
453 
454 	/* Check authors */
455 	list = gdata_entry_get_authors (entry);
456 	g_assert_cmpuint (g_list_length (list), ==, 3);
457 
458 	author = GDATA_AUTHOR (list->data);
459 	g_assert (author != NULL);
460 	g_assert_cmpstr (gdata_author_get_name (author), ==, "F. Barr؟");
461 	g_assert (gdata_author_get_uri (author) == NULL);
462 	g_assert (gdata_author_get_email_address (author) == NULL);
463 
464 	author = GDATA_AUTHOR (list->next->data);
465 	g_assert (author != NULL);
466 	g_assert_cmpstr (gdata_author_get_name (author), ==, "John Smith");
467 	g_assert (gdata_author_get_uri (author) == NULL);
468 	g_assert_cmpstr (gdata_author_get_email_address (author), ==, "smith.john@example.com");
469 
470 	author = GDATA_AUTHOR (list->next->next->data);
471 	g_assert (author != NULL);
472 	g_assert_cmpstr (gdata_author_get_name (author), ==, "Joe Bloggs");
473 	g_assert_cmpstr (gdata_author_get_uri (author), ==, "http://example.com/");
474 	g_assert_cmpstr (gdata_author_get_email_address (author), ==, "joe@example.com");
475 
476 	/* Check categories */
477 	list = gdata_entry_get_categories (entry);
478 	g_assert (list != NULL);
479 	g_assert_cmpint (g_list_length (list), ==, 3);
480 
481 	category = GDATA_CATEGORY (list->data);
482 	g_assert (category != NULL);
483 	g_assert_cmpstr (gdata_category_get_term (category), ==, "Film");
484 	g_assert_cmpstr (gdata_category_get_scheme (category), ==, "http://gdata.youtube.com/schemas/2007/categories.cat");
485 	g_assert_cmpstr (gdata_category_get_label (category), ==, "Film & Animation");
486 
487 	category = GDATA_CATEGORY (list->next->data);
488 	g_assert (category != NULL);
489 	g_assert_cmpstr (gdata_category_get_term (category), ==, "example");
490 	g_assert (gdata_category_get_scheme (category) == NULL);
491 	g_assert_cmpstr (gdata_category_get_label (category), ==, "Example stuff");
492 
493 	category = GDATA_CATEGORY (list->next->next->data);
494 	g_assert (category != NULL);
495 	g_assert_cmpstr (gdata_category_get_term (category), ==, "test");
496 	g_assert (gdata_category_get_scheme (category) == NULL);
497 	g_assert (gdata_category_get_label (category) == NULL);
498 
499 	/* TODO: Check authors */
500 
501 	/* Check properties a different way */
502 	g_object_get (G_OBJECT (entry2),
503 	              "title", &title,
504 	              "summary", &summary,
505 	              "id", &id,
506 	              "etag", &etag,
507 	              "updated", &updated3,
508 	              "published", &published3,
509 	              "content", &content,
510 	              "content-uri", &content_uri,
511 	              "is-inserted", &is_inserted,
512 	              "rights", &rights,
513 	              NULL);
514 
515 	g_assert_cmpstr (title, ==, gdata_entry_get_title (entry));
516 	g_assert_cmpstr (summary, ==, gdata_entry_get_summary (entry));
517 	g_assert_cmpstr (id, ==, gdata_entry_get_id (entry));
518 	g_assert_cmpstr (etag, ==, gdata_entry_get_etag (entry));
519 	g_assert_cmpint (updated3, ==, updated);
520 	g_assert_cmpint (published3, ==, published);
521 	g_assert_cmpstr (content, ==, gdata_entry_get_content (entry));
522 	g_assert_cmpstr (content_uri, ==, gdata_entry_get_content_uri (entry));
523 	g_assert (is_inserted == FALSE);
524 	g_assert_cmpstr (rights, ==, gdata_entry_get_rights (entry));
525 
526 	g_free (title);
527 	g_free (summary);
528 	g_free (id);
529 	g_free (etag);
530 	g_free (content);
531 	g_free (content_uri);
532 	g_free (rights);
533 
534 	/* Set the content URI and check that */
535 	gdata_entry_set_content_uri (entry, "http://baz.net/");
536 
537 	g_object_get (G_OBJECT (entry),
538 	              "content", &content,
539 	              "content-uri", &content_uri,
540 	              NULL);
541 
542 	g_assert_cmpstr (content, ==, gdata_entry_get_content (entry));
543 	g_assert_cmpstr (content_uri, ==, gdata_entry_get_content_uri (entry));
544 
545 	g_free (content);
546 	g_free (content_uri);
547 
548 	g_object_unref (entry);
549 	g_object_unref (entry2);
550 }
551 
552 static void
test_entry_get_json(void)553 test_entry_get_json (void)
554 {
555 	gint64 updated, published, updated2, published2;
556 	GDataEntry *entry, *entry2;
557 	gchar *json;
558 	GError *error = NULL;
559 
560 	entry = gdata_entry_new (NULL);
561 
562 	/* Set the properties more conventionally */
563 	gdata_entry_set_title (entry, "Testing title & \"escaping\"");
564 	gdata_entry_set_summary (entry, NULL);
565 	gdata_entry_set_content (entry, NULL);
566 	gdata_entry_set_rights (entry, NULL);
567 
568 	/* Check the generated JSON's OK */
569 	gdata_test_assert_json (entry,
570 		"{"
571 			"\"title\":\"Testing title & \\\"escaping\\\"\""
572 		"}");
573 
574 	/* Check again by re-parsing the JSON to a GDataEntry. */
575 	json = gdata_parsable_get_json (GDATA_PARSABLE (entry));
576 	entry2 = GDATA_ENTRY (gdata_parsable_new_from_json (GDATA_TYPE_ENTRY, json, -1, &error));
577 	g_assert_no_error (error);
578 	g_assert (GDATA_IS_ENTRY (entry2));
579 	g_clear_error (&error);
580 	g_free (json);
581 
582 	g_assert_cmpstr (gdata_entry_get_title (entry), ==, gdata_entry_get_title (entry2));
583 	g_assert_cmpstr (gdata_entry_get_id (entry), ==, gdata_entry_get_id (entry2)); /* should both be NULL */
584 	g_assert_cmpstr (gdata_entry_get_content (entry), ==, gdata_entry_get_content (entry2));
585 	g_assert_cmpstr (gdata_entry_get_content_uri (entry), ==, gdata_entry_get_content_uri (entry2)); /* should both be NULL */
586 
587 	updated = gdata_entry_get_updated (entry);
588 	updated2 = gdata_entry_get_updated (entry2);
589 	g_assert_cmpuint (updated, ==, updated2);
590 
591 	published = gdata_entry_get_published (entry);
592 	published2 = gdata_entry_get_published (entry2);
593 	g_assert_cmpuint (published, ==, published2);
594 
595 	g_object_unref (entry);
596 	g_object_unref (entry2);
597 }
598 
599 static void
test_entry_parse_xml(void)600 test_entry_parse_xml (void)
601 {
602 	GDataEntry *entry;
603 	GError *error = NULL;
604 
605 	/* Create an entry from XML with unhandled elements */
606 	entry = GDATA_ENTRY (gdata_parsable_new_from_xml (GDATA_TYPE_ENTRY,
607 		"<entry xmlns='http://www.w3.org/2005/Atom' xmlns:ns='http://example.com/'>"
608 			"<title type='text'>Testing unhandled XML</title>"
609 			"<updated>2009-01-25T14:07:37Z</updated>"
610 			"<published>2009-01-23T14:06:37Z</published>"
611 			"<content type='text'>Here we test unhandled XML elements.</content>"
612 			"<foobar>Test!</foobar>"
613 			"<barfoo shizzle='zing'/>"
614 			"<ns:barfoo shizzle='zing' fo='shizzle'>How about some characters‽</ns:barfoo>"
615 		 "</entry>", -1, &error));
616 	g_assert_no_error (error);
617 	g_assert (GDATA_IS_ENTRY (entry));
618 	g_clear_error (&error);
619 
620 	/* Now check the outputted XML from the entry still has the unhandled elements */
621 	gdata_test_assert_xml (entry,
622 			 "<?xml version='1.0' encoding='UTF-8'?>"
623 			 "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' xmlns:ns='http://example.com/'>"
624 				"<title type='text'>Testing unhandled XML</title>"
625 				"<updated>2009-01-25T14:07:37Z</updated>"
626 				"<published>2009-01-23T14:06:37Z</published>"
627 				"<content type='text'>Here we test unhandled XML elements.</content>"
628 				"<foobar>Test!</foobar>"
629 				"<barfoo shizzle=\"zing\"/>"
630 				"<ns:barfoo shizzle=\"zing\" fo=\"shizzle\">How about some characters‽</ns:barfoo>"
631 			 "</entry>");
632 	g_object_unref (entry);
633 }
634 
635 static void
test_entry_parse_xml_kind_category(void)636 test_entry_parse_xml_kind_category (void)
637 {
638 	GDataEntry *entry;
639 	GError *error = NULL;
640 
641 	g_test_bug ("707477");
642 
643 	/* Create an entry from XML with a ‘kind’ category with extra attributes. */
644 	entry = GDATA_ENTRY (gdata_parsable_new_from_xml (GDATA_TYPE_ENTRY,
645 		"<entry xmlns='http://www.w3.org/2005/Atom'>"
646 			"<title type='text'>Testing kind categories</title>"
647 			"<updated>2009-01-25T14:07:37Z</updated>"
648 			"<published>2009-01-23T14:06:37Z</published>"
649 			"<content type='text'>Here we test kind categories.</content>"
650 			"<category scheme='http://schemas.google.com/g/2005#kind' "
651 			          "term='http://schemas.google.com/docs/2007#file' "
652 			          "label='application/vnd.oasis.opendocument.presentation'/>"
653 			"<category scheme='http://schemas.google.com/g/2005/labels' "
654 			          "term='http://schemas.google.com/g/2005/labels#modified-by-me' "
655 			          "label='modified-by-me'/>"
656 		 "</entry>", -1, &error));
657 	g_assert_no_error (error);
658 	g_assert (GDATA_IS_ENTRY (entry));
659 	g_clear_error (&error);
660 
661 	/* Now check the outputted XML from the entry still has the extra attributes */
662 	gdata_test_assert_xml (entry,
663 			 "<?xml version='1.0' encoding='UTF-8'?>"
664 			 "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005'>"
665 				"<title type='text'>Testing kind categories</title>"
666 				"<updated>2009-01-25T14:07:37Z</updated>"
667 				"<published>2009-01-23T14:06:37Z</published>"
668 				"<content type='text'>Here we test kind categories.</content>"
669 			"<category term='http://schemas.google.com/docs/2007#file' "
670 			          "scheme='http://schemas.google.com/g/2005#kind' "
671 			          "label='application/vnd.oasis.opendocument.presentation'/>"
672 			"<category term='http://schemas.google.com/g/2005/labels#modified-by-me' "
673 			          "scheme='http://schemas.google.com/g/2005/labels' "
674 			          "label='modified-by-me'/>"
675 			 "</entry>");
676 	g_object_unref (entry);
677 }
678 
679 static void
test_entry_parse_json(void)680 test_entry_parse_json (void)
681 {
682 	GDataEntry *entry;
683 	GError *error = NULL;
684 
685 	/* Create an entry from JSON with unhandled nodes. */
686 	entry = GDATA_ENTRY (gdata_parsable_new_from_json (GDATA_TYPE_ENTRY,
687 		"{"
688 			"\"title\":\"A title\","
689 			"\"updated\":\"2009-01-25T14:07:37Z\","
690 			"\"selfLink\":\"http://example.com/\","
691 			"\"etag\":\"some-etag\","
692 			"\"id\":\"some-id\","
693 			"\"kind\":\"kind#kind\","
694 			"\"unhandled-boolean\":false,"
695 			"\"unhandled-string\":\"this-is-a-string---sometimes\","
696 			"\"unhandled-int\":15,"
697 			"\"unhandled-double\":42.42,"
698 			"\"unhandled-object\":{"
699 				"\"a\":true,"
700 				"\"b\":true"
701 			"},"
702 			"\"unhandled-array\":["
703 				"1,"
704 				"2,"
705 				"3"
706 			"],"
707 			"\"unhandled-null\":null"
708 		 "}", -1, &error));
709 	g_assert_no_error (error);
710 	g_assert (GDATA_IS_ENTRY (entry));
711 
712 	/* Now check the outputted JSON from the entry still has the unhandled nodes. */
713 	gdata_test_assert_json (entry,
714 		"{"
715 			"\"title\":\"A title\","
716 			"\"id\":\"some-id\","
717 			"\"updated\":\"2009-01-25T14:07:37Z\","
718 			"\"etag\":\"some-etag\","
719 			"\"selfLink\":\"http://example.com/\","
720 			"\"kind\":\"kind#kind\","
721 			"\"unhandled-boolean\":false,"
722 			"\"unhandled-string\":\"this-is-a-string---sometimes\","
723 			"\"unhandled-int\":15,"
724 			"\"unhandled-double\":42.42,"
725 			"\"unhandled-object\":{"
726 				"\"a\":true,"
727 				"\"b\":true"
728 			"},"
729 			"\"unhandled-array\":["
730 				"1,"
731 				"2,"
732 				"3"
733 			"],"
734 			"\"unhandled-null\":null"
735 		 "}");
736 	g_object_unref (entry);
737 
738 	/* Test parsing of empty titles. */
739 	entry = GDATA_ENTRY (gdata_parsable_new_from_json (GDATA_TYPE_ENTRY,
740 		"{"
741 			"\"title\":\"\""
742 		 "}", -1, &error));
743 	g_assert_no_error (error);
744 	g_assert (GDATA_IS_ENTRY (entry));
745 	g_object_unref (entry);
746 }
747 
748 static void
test_entry_error_handling_xml(void)749 test_entry_error_handling_xml (void)
750 {
751 	GDataEntry *entry;
752 	GError *error = NULL;
753 
754 #define TEST_XML_ERROR_HANDLING(x) entry = GDATA_ENTRY (gdata_parsable_new_from_xml (GDATA_TYPE_ENTRY,\
755 		"<entry>"\
756 			x\
757 		"</entry>", -1, &error));\
758 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);\
759 	g_assert (entry == NULL);\
760 	g_clear_error (&error)
761 
762 	/* updated */
763 	TEST_XML_ERROR_HANDLING ("<updated>not a date</updated>"); /* invalid date */
764 
765 	/* published */
766 	TEST_XML_ERROR_HANDLING ("<published>also not a date</published>"); /* invalid date */
767 
768 	/* category */
769 	TEST_XML_ERROR_HANDLING ("<category/>"); /* invalid category */
770 
771 	/* link */
772 	TEST_XML_ERROR_HANDLING ("<link/>"); /* invalid link */
773 
774 	/* author */
775 	TEST_XML_ERROR_HANDLING ("<author/>"); /* invalid author */
776 
777 #undef TEST_XML_ERROR_HANDLING
778 }
779 
780 static void
test_entry_error_handling_json(void)781 test_entry_error_handling_json (void)
782 {
783 	GDataEntry *entry;
784 	GError *error = NULL;
785 
786 #define TEST_JSON_ERROR_HANDLING(x) \
787 	entry = GDATA_ENTRY (gdata_parsable_new_from_json (GDATA_TYPE_ENTRY,x, -1, &error));\
788 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);\
789 	g_assert (entry == NULL);\
790 	g_clear_error (&error)
791 #define TEST_JSON_ERROR_HANDLING_PARSER(x) \
792 	entry = GDATA_ENTRY (gdata_parsable_new_from_json (GDATA_TYPE_ENTRY,x, -1, &error));\
793 	g_assert_error (error, GDATA_PARSER_ERROR, GDATA_PARSER_ERROR_PARSING_STRING);\
794 	g_assert (entry == NULL);\
795 	g_clear_error (&error)
796 
797 	/* General structure. */
798 	TEST_JSON_ERROR_HANDLING_PARSER ("[true,false,true]"); /* root node is not an object */
799 	TEST_JSON_ERROR_HANDLING_PARSER ("false"); /* root node is not an object */
800 	TEST_JSON_ERROR_HANDLING_PARSER ("invalid json"); /* totally invalid JSON */
801 
802 	/* id */
803 	TEST_JSON_ERROR_HANDLING ("{\"id\":\"\"}"); /* empty */
804 	TEST_JSON_ERROR_HANDLING ("{\"id\":null}"); /* invalid type */
805 
806 	/* updated */
807 	TEST_JSON_ERROR_HANDLING ("{\"updated\":\"not correct\"}"); /* incorrect format */
808 	TEST_JSON_ERROR_HANDLING ("{\"updated\":false}"); /* invalid type */
809 	TEST_JSON_ERROR_HANDLING ("{\"updated\":\"\"}"); /* empty */
810 
811 	/* title */
812 	TEST_JSON_ERROR_HANDLING ("{\"title\":false}"); /* invalid type */
813 
814 	/* etag */
815 	TEST_JSON_ERROR_HANDLING ("{\"etag\":\"\"}"); /* empty */
816 	TEST_JSON_ERROR_HANDLING ("{\"etag\":false}"); /* invalid type */
817 
818 	/* selfLink */
819 	TEST_JSON_ERROR_HANDLING ("{\"selfLink\":\"\"}"); /* empty */
820 	TEST_JSON_ERROR_HANDLING ("{\"selfLink\":false}"); /* invalid type */
821 
822 	/* kind */
823 	TEST_JSON_ERROR_HANDLING ("{\"kind\":\"\"}"); /* empty */
824 	TEST_JSON_ERROR_HANDLING ("{\"kind\":false}"); /* invalid type */
825 
826 #undef TEST_JSON_ERROR_HANDLING_PARSER
827 #undef TEST_JSON_ERROR_HANDLING
828 }
829 
830 static void
test_entry_escaping(void)831 test_entry_escaping (void)
832 {
833 	GDataEntry *entry;
834 	GError *error = NULL;
835 
836 	/* Since we can't construct a GDataEntry directly, we need to parse it from XML */
837 	entry = GDATA_ENTRY (gdata_parsable_new_from_xml (GDATA_TYPE_ENTRY,
838 		"<?xml version='1.0' encoding='UTF-8'?>"
839 		"<entry xmlns='http://www.w3.org/2005/Atom'>"
840 			"<title type='text'>Escaped content &amp; stuff</title>"
841 			"<id>http://foo.com/?foo&amp;bar</id>"
842 			"<updated>2010-12-10T17:21:24Z</updated>"
843 			"<published>2010-12-10T17:21:24Z</published>"
844 			"<summary type='text'>Summary &amp; stuff</summary>"
845 			"<rights>Free &amp; open source</rights>"
846 			"<content type='text'>Content &amp; things.</content>"
847 		"</entry>", -1, &error));
848 	g_assert_no_error (error);
849 	g_assert (GDATA_IS_ENTRY (entry));
850 
851 	/* Check the outputted XML is escaped properly */
852 	gdata_test_assert_xml (entry,
853 		"<?xml version='1.0' encoding='UTF-8'?>"
854 		"<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005'>"
855 			"<title type='text'>Escaped content &amp; stuff</title>"
856 			"<id>http://foo.com/?foo&amp;bar</id>"
857 			"<updated>2010-12-10T17:21:24Z</updated>"
858 			"<published>2010-12-10T17:21:24Z</published>"
859 			"<summary type='text'>Summary &amp; stuff</summary>"
860 			"<rights>Free &amp; open source</rights>"
861 			"<content type='text'>Content &amp; things.</content>"
862 		"</entry>");
863 	g_object_unref (entry);
864 
865 	/* Repeat with content given by a URI */
866 	entry = GDATA_ENTRY (gdata_parsable_new_from_xml (GDATA_TYPE_ENTRY,
867 		"<?xml version='1.0' encoding='UTF-8'?>"
868 		"<entry xmlns='http://www.w3.org/2005/Atom'>"
869 			"<title type='text'>Escaped content &amp; stuff</title>"
870 			"<content type='text/plain' src='http://foo.com?foo&amp;bar'/>"
871 		"</entry>", -1, &error));
872 	g_assert_no_error (error);
873 	g_assert (GDATA_IS_ENTRY (entry));
874 
875 	/* Check the outputted XML is escaped properly */
876 	gdata_test_assert_xml (entry,
877 		"<?xml version='1.0' encoding='UTF-8'?>"
878 		"<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005'>"
879 			"<title type='text'>Escaped content &amp; stuff</title>"
880 			"<content type='text/plain' src='http://foo.com?foo&amp;bar'/>"
881 		"</entry>");
882 	g_object_unref (entry);
883 }
884 
885 static void
test_entry_links_remove(void)886 test_entry_links_remove (void)
887 {
888 	GDataEntry *entry;
889 	GDataLink *link_, *link2_;
890 	GError *error = NULL;
891 
892 	/* Since we can't construct a GDataEntry directly, we need to parse it from XML. */
893 	entry = GDATA_ENTRY (gdata_parsable_new_from_xml (GDATA_TYPE_ENTRY,
894 		"<?xml version='1.0' encoding='UTF-8'?>"
895 		"<entry xmlns='http://www.w3.org/2005/Atom'>"
896 			"<title type='text'>Escaped content &amp; stuff</title>"
897 			"<id>http://foo.com/?foo&amp;bar</id>"
898 			"<updated>2010-12-10T17:21:24Z</updated>"
899 			"<published>2010-12-10T17:21:24Z</published>"
900 			"<summary type='text'>Summary &amp; stuff</summary>"
901 			"<rights>Free &amp; open source</rights>"
902 			"<content type='text'>Content &amp; things.</content>"
903 		"</entry>", -1, &error));
904 	g_assert_no_error (error);
905 	g_assert (GDATA_IS_ENTRY (entry));
906 
907 	link_ = gdata_link_new ("http://example.com/", GDATA_LINK_RELATED);
908 
909 	/* Add a link. */
910 	gdata_entry_add_link (entry, link_);
911 	g_assert (gdata_entry_look_up_link (entry, GDATA_LINK_RELATED) == link_);
912 
913 	/* Remove the link. */
914 	g_assert (gdata_entry_remove_link (entry, link_) == TRUE);
915 	g_assert (gdata_entry_look_up_link (entry, GDATA_LINK_RELATED) == NULL);
916 
917 	/* Attempt to remove a non-existent link. */
918 	link2_ = gdata_link_new ("http://foobar.com/", GDATA_LINK_SELF);
919 	g_assert (gdata_entry_remove_link (entry, link2_) == FALSE);
920 
921 	g_object_unref (link2_);
922 	g_object_unref (link_);
923 	g_object_unref (entry);
924 }
925 
926 static void
test_feed_parse_xml(void)927 test_feed_parse_xml (void)
928 {
929 	GDataFeed *feed;
930 	GDataEntry *entry;
931 	GDataLink *_link; /* stupid unistd.h */
932 	GList *list;
933 	gchar *title, *subtitle, *id, *etag, *logo, *icon, *rights;
934 	gint64 updated, updated2;
935 	GDataGenerator *generator;
936 	guint items_per_page, start_index, total_results;
937 	GError *error = NULL;
938 
939 	feed = GDATA_FEED (gdata_parsable_new_from_xml (GDATA_TYPE_FEED,
940 		"<feed xmlns='http://www.w3.org/2005/Atom' "
941 		      "xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' "
942 		      "xmlns:gd='http://schemas.google.com/g/2005' "
943 		      "gd:etag='W/\"D08FQn8-eil7ImA9WxZbFEw.\"'>"
944 			"<id>http://example.com/id</id>"
945 			"<updated>2009-02-25T14:07:37.880860Z</updated>"
946 			"<title type='text'>Test feed</title>"
947 			"<subtitle type='text'>Test subtitle</subtitle>"
948 			"<logo>http://example.com/logo.png</logo>"
949 			"<icon>http://example.com/icon.png</icon>"
950 			"<link rel='alternate' type='text/html' href='http://alternate.example.com/'/>"
951 			"<link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://example.com/id'/>"
952 			"<link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' href='http://example.com/post'/>"
953 			"<link rel='self' type='application/atom+xml' href='http://example.com/id'/>"
954 			"<category scheme='http://example.com/categories' term='feed'/>"
955 			"<rights>public</rights>"
956 			"<author>"
957 				"<name>Joe Smith</name>"
958 				"<email>j.smith@example.com</email>"
959 			"</author>"
960 			"<generator version='0.6' uri='http://example.com/'>Example Generator</generator>"
961 			"<openSearch:totalResults>2</openSearch:totalResults>"
962 			"<openSearch:startIndex>1</openSearch:startIndex>"
963 			"<openSearch:itemsPerPage>50</openSearch:itemsPerPage>"
964 			"<entry>"
965 				"<id>entry1</id>"
966 				"<title type='text'>Testing unhandled XML</title>"
967 				"<updated>2009-01-25T14:07:37.880860Z</updated>"
968 				"<published>2009-01-23T14:06:37.880860Z</published>"
969 				"<content type='text'>Here we test unhandled XML elements.</content>"
970 			"</entry>"
971 			"<entry>"
972 				"<id>entry2</id>"
973 				"<title type='text'>Testing unhandled XML 2</title>"
974 				"<updated>2009-02-25T14:07:37.880860Z</updated>"
975 				"<published>2009-02-23T14:06:37.880860Z</published>"
976 				"<content type='text'>Here we test unhandled XML elements again.</content>"
977 			"</entry>"
978 			"<foobar>Test unhandled elements!</foobar>"
979 		"</feed>", -1, &error));
980 	g_assert_no_error (error);
981 	g_assert (GDATA_IS_FEED (feed));
982 	g_clear_error (&error);
983 
984 	/* Check the feed's properties */
985 	g_object_get (G_OBJECT (feed),
986 	              "title", &title,
987 	              "subtitle", &subtitle,
988 	              "id", &id,
989 	              "etag", &etag,
990 	              "updated", &updated,
991 	              "logo", &logo,
992 	              "icon", &icon,
993 	              "generator", &generator,
994 	              "rights", &rights,
995 	              "items-per-page", &items_per_page,
996 	              "start-index", &start_index,
997 	              "total-results", &total_results,
998 	              NULL);
999 
1000 	g_assert_cmpstr (title, ==, "Test feed");
1001 	g_assert_cmpstr (subtitle, ==, "Test subtitle");
1002 	g_assert_cmpstr (id, ==, "http://example.com/id");
1003 	g_assert_cmpstr (etag, ==, "W/\"D08FQn8-eil7ImA9WxZbFEw.\"");
1004 
1005 	g_assert_cmpint (updated, ==, 1235570857);
1006 
1007 	g_assert_cmpstr (logo, ==, "http://example.com/logo.png");
1008 	g_assert_cmpstr (icon, ==, "http://example.com/icon.png");
1009 	g_assert_cmpstr (rights, ==, "public");
1010 
1011 	g_assert (GDATA_IS_GENERATOR (generator));
1012 	g_assert_cmpstr (gdata_generator_get_name (generator), ==, "Example Generator");
1013 	g_assert_cmpstr (gdata_generator_get_uri (generator), ==, "http://example.com/");
1014 	g_assert_cmpstr (gdata_generator_get_version (generator), ==, "0.6");
1015 
1016 	g_assert_cmpuint (items_per_page, ==, 50);
1017 	g_assert_cmpuint (start_index, ==, 1);
1018 	g_assert_cmpuint (total_results, ==, 2);
1019 
1020 	g_free (title);
1021 	g_free (subtitle);
1022 	g_free (id);
1023 	g_free (etag);
1024 	g_free (logo);
1025 	g_free (icon);
1026 	g_free (rights);
1027 	g_object_unref (generator);
1028 
1029 	/* Check the entries */
1030 	entry = gdata_feed_look_up_entry (feed, "entry1");
1031 	g_assert (GDATA_IS_ENTRY (entry));
1032 
1033 	entry = gdata_feed_look_up_entry (feed, "this doesn't exist");
1034 	g_assert (entry == NULL);
1035 
1036 	entry = gdata_feed_look_up_entry (feed, "entry2");
1037 	g_assert (GDATA_IS_ENTRY (entry));
1038 
1039 	/* Check the categories */
1040 	list = gdata_feed_get_categories (feed);
1041 	g_assert (list != NULL);
1042 	g_assert_cmpint (g_list_length (list), ==, 1);
1043 	g_assert (GDATA_IS_CATEGORY (list->data));
1044 
1045 	/* Check the links */
1046 	list = gdata_feed_get_links (feed);
1047 	g_assert (list != NULL);
1048 	g_assert_cmpint (g_list_length (list), ==, 4);
1049 	g_assert (GDATA_IS_LINK (list->data));
1050 	g_assert (GDATA_IS_LINK (list->next->data));
1051 	g_assert (GDATA_IS_LINK (list->next->next->data));
1052 	g_assert (GDATA_IS_LINK (list->next->next->next->data));
1053 
1054 	_link = gdata_feed_look_up_link (feed, GDATA_LINK_ALTERNATE);
1055 	g_assert (GDATA_IS_LINK (_link));
1056 
1057 	_link = gdata_feed_look_up_link (feed, "this doesn't exist");
1058 	g_assert (_link == NULL);
1059 
1060 	_link = gdata_feed_look_up_link (feed, "http://schemas.google.com/g/2005#feed");
1061 	g_assert (GDATA_IS_LINK (_link));
1062 
1063 	_link = gdata_feed_look_up_link (feed, "http://schemas.google.com/g/2005#post");
1064 	g_assert (GDATA_IS_LINK (_link));
1065 
1066 	_link = gdata_feed_look_up_link (feed, GDATA_LINK_SELF);
1067 	g_assert (GDATA_IS_LINK (_link));
1068 
1069 	/* Check the authors */
1070 	list = gdata_feed_get_authors (feed);
1071 	g_assert (list != NULL);
1072 	g_assert_cmpint (g_list_length (list), ==, 1);
1073 	g_assert (GDATA_IS_AUTHOR (list->data));
1074 
1075 	/* Check the other properties again, the more normal way this time */
1076 	g_assert_cmpstr (gdata_feed_get_title (feed), ==, "Test feed");
1077 	g_assert_cmpstr (gdata_feed_get_subtitle (feed), ==, "Test subtitle");
1078 	g_assert_cmpstr (gdata_feed_get_id (feed), ==, "http://example.com/id");
1079 	g_assert_cmpstr (gdata_feed_get_etag (feed), ==, "W/\"D08FQn8-eil7ImA9WxZbFEw.\"");
1080 
1081 	updated2 = gdata_feed_get_updated (feed);
1082 	g_assert_cmpint (updated2, ==, 1235570857);
1083 
1084 	g_assert_cmpstr (gdata_feed_get_logo (feed), ==, "http://example.com/logo.png");
1085 	g_assert_cmpstr (gdata_feed_get_icon (feed), ==, "http://example.com/icon.png");
1086 	g_assert_cmpstr (gdata_feed_get_rights (feed), ==, "public");
1087 
1088 	generator = gdata_feed_get_generator (feed);
1089 	g_assert (GDATA_IS_GENERATOR (generator));
1090 	g_assert_cmpstr (gdata_generator_get_name (generator), ==, "Example Generator");
1091 	g_assert_cmpstr (gdata_generator_get_uri (generator), ==, "http://example.com/");
1092 	g_assert_cmpstr (gdata_generator_get_version (generator), ==, "0.6");
1093 
1094 	g_assert_cmpuint (gdata_feed_get_items_per_page (feed), ==, 50);
1095 	g_assert_cmpuint (gdata_feed_get_start_index (feed), ==, 1);
1096 	g_assert_cmpuint (gdata_feed_get_total_results (feed), ==, 2);
1097 
1098 	g_object_unref (feed);
1099 }
1100 
1101 static void
test_feed_error_handling(void)1102 test_feed_error_handling (void)
1103 {
1104 	GDataFeed *feed;
1105 	GError *error = NULL;
1106 
1107 #define TEST_XML_ERROR_HANDLING(x) feed = GDATA_FEED (gdata_parsable_new_from_xml (GDATA_TYPE_FEED, \
1108 		"<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/'>"\
1109 			x\
1110 		"</feed>", -1, &error));\
1111 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);\
1112 	g_assert (feed == NULL);\
1113 	g_clear_error (&error)
1114 
1115 	/* entry */
1116 	TEST_XML_ERROR_HANDLING ("<entry><updated>this isn't a date</updated></entry>"); /* invalid entry */
1117 
1118 	/* title */
1119 	TEST_XML_ERROR_HANDLING ("<title>First title</title><title>Second title</title>"); /* duplicate title */
1120 #if 0
1121 	/* FIXME: Removed due to the YouTube comments feed not being a valid Atom feed.
1122 	 * See: https://code.google.com/p/gdata-issues/issues/detail?id=2908
1123 	 * and: https://bugzilla.gnome.org/show_bug.cgi?id=679072 */
1124 	TEST_XML_ERROR_HANDLING ("<id>ID</id><updated>2009-01-25T14:07:37.880860Z</updated>"); /* missing title */
1125 #endif
1126 
1127 	/* subtitle */
1128 	TEST_XML_ERROR_HANDLING ("<subtitle>First subtitle</subtitle><subtitle>Second subtitle</subtitle>"); /* duplicate subtitle */
1129 
1130 	/* id */
1131 	TEST_XML_ERROR_HANDLING ("<id>First ID</id><id>Second ID</id>"); /* duplicate ID */
1132 	TEST_XML_ERROR_HANDLING ("<title>Title</title><updated>2009-01-25T14:07:37.880860Z</updated>"); /* missing ID */
1133 
1134 	/* updated */
1135 	TEST_XML_ERROR_HANDLING ("<updated>2009-01-25T14:07:37.880860Z</updated>"
1136 	                         "<updated>2009-01-25T14:07:37.880860Z</updated>"); /* duplicate updated */
1137 	TEST_XML_ERROR_HANDLING ("<updated>not a date</updated>"); /* invalid date */
1138 	TEST_XML_ERROR_HANDLING ("<title>Title</title><id>ID</id>"); /* missing updated */
1139 
1140 	/* category */
1141 	TEST_XML_ERROR_HANDLING ("<category/>"); /* invalid category */
1142 
1143 	/* logo */
1144 	TEST_XML_ERROR_HANDLING ("<logo>First logo</logo><logo>Second logo</logo>"); /* duplicate logo */
1145 
1146 	/* icon */
1147 	TEST_XML_ERROR_HANDLING ("<icon>First icon</icon><icon>Second icon</icon>"); /* duplicate icon */
1148 
1149 	/* link */
1150 	TEST_XML_ERROR_HANDLING ("<link/>"); /* invalid link */
1151 
1152 	/* author */
1153 	TEST_XML_ERROR_HANDLING ("<author/>"); /* invalid author */
1154 
1155 	/* generator */
1156 	TEST_XML_ERROR_HANDLING ("<generator>First generator</generator><generator>Second generator</generator>"); /* duplicate generator */
1157 	TEST_XML_ERROR_HANDLING ("<generator uri=''/>"); /* invalid generator */
1158 
1159 	/* openSearch:totalResults */
1160 	TEST_XML_ERROR_HANDLING ("<openSearch:totalResults>5</openSearch:totalResults>"
1161 	                         "<openSearch:totalResults>3</openSearch:totalResults>"); /* duplicate totalResults */
1162 	TEST_XML_ERROR_HANDLING ("<openSearch:totalResults></openSearch:totalResults>"); /* missing content */
1163 	TEST_XML_ERROR_HANDLING ("<openSearch:totalResults>this isn't a number!</openSearch:totalResults>"); /* invalid number */
1164 
1165 	/* openSearch:startIndex */
1166 	TEST_XML_ERROR_HANDLING ("<openSearch:startIndex>5</openSearch:startIndex>"
1167 	                         "<openSearch:startIndex>3</openSearch:startIndex>"); /* duplicate startIndex */
1168 	TEST_XML_ERROR_HANDLING ("<openSearch:startIndex></openSearch:startIndex>"); /* missing content */
1169 	TEST_XML_ERROR_HANDLING ("<openSearch:startIndex>this isn't a number!</openSearch:startIndex>"); /* invalid number */
1170 
1171 	/* openSearch:itemsPerPage */
1172 	TEST_XML_ERROR_HANDLING ("<openSearch:itemsPerPage>5</openSearch:itemsPerPage>"
1173 	                         "<openSearch:itemsPerPage>3</openSearch:itemsPerPage>"); /* duplicate itemsPerPage */
1174 	TEST_XML_ERROR_HANDLING ("<openSearch:itemsPerPage></openSearch:itemsPerPage>"); /* missing content */
1175 	TEST_XML_ERROR_HANDLING ("<openSearch:itemsPerPage>this isn't a number!</openSearch:itemsPerPage>"); /* invalid number */
1176 
1177 #undef TEST_XML_ERROR_HANDLING
1178 }
1179 
1180 static void
test_feed_escaping(void)1181 test_feed_escaping (void)
1182 {
1183 	GDataFeed *feed;
1184 	GError *error = NULL;
1185 
1186 	/* Since we can't construct a GDataEntry directly, we need to parse it from XML */
1187 	feed = GDATA_FEED (gdata_parsable_new_from_xml (GDATA_TYPE_FEED,
1188 		"<?xml version='1.0' encoding='UTF-8'?>"
1189 		"<feed xmlns='http://www.w3.org/2005/Atom'>"
1190 			"<id>http://foo.com?foo&amp;bar</id>"
1191 			"<updated>2010-12-10T17:49:15Z</updated>"
1192 			"<title type='text'>Test feed &amp; stuff.</title>"
1193 		"</feed>", -1, &error));
1194 	g_assert_no_error (error);
1195 	g_assert (GDATA_IS_FEED (feed));
1196 
1197 	/* Check the outputted XML is escaped properly */
1198 	gdata_test_assert_xml (feed,
1199 		"<?xml version='1.0' encoding='UTF-8'?>"
1200 		"<feed xmlns='http://www.w3.org/2005/Atom'>"
1201 			"<title type='text'>Test feed &amp; stuff.</title>"
1202 			"<id>http://foo.com?foo&amp;bar</id>"
1203 			"<updated>2010-12-10T17:49:15Z</updated>"
1204 		"</feed>");
1205 	g_object_unref (feed);
1206 }
1207 
1208 static void
test_query_categories(void)1209 test_query_categories (void)
1210 {
1211 	GDataQuery *query;
1212 	gchar *query_uri;
1213 
1214 	query = gdata_query_new ("foobar");
1215 
1216 	/* AND */
1217 	gdata_query_set_categories (query, "Fritz/Laurie");
1218 	query_uri = gdata_query_get_query_uri (query, "http://example.com");
1219 	g_assert_cmpstr (query_uri, ==, "http://example.com/-/Fritz/Laurie?q=foobar");
1220 	g_free (query_uri);
1221 
1222 	/* OR */
1223 	gdata_query_set_categories (query, "Fritz|Laurie");
1224 	query_uri = gdata_query_get_query_uri (query, "http://example.com");
1225 	g_assert_cmpstr (query_uri, ==, "http://example.com/-/Fritz%7CLaurie?q=foobar");
1226 	g_free (query_uri);
1227 
1228 	/* Combination */
1229 	gdata_query_set_categories (query, "A|-{urn:google.com}B/-C");
1230 	query_uri = gdata_query_get_query_uri (query, "http://example.com/gdata_test");
1231 	g_assert_cmpstr (query_uri, ==, "http://example.com/gdata_test/-/A%7C-%7Burn%3Agoogle.com%7DB/-C?q=foobar");
1232 	g_free (query_uri);
1233 
1234 	/* Same combination without q param */
1235 	gdata_query_set_q (query, NULL);
1236 	query_uri = gdata_query_get_query_uri (query, "http://example.com");
1237 	g_assert_cmpstr (query_uri, ==, "http://example.com/-/A%7C-%7Burn%3Agoogle.com%7DB/-C");
1238 	g_free (query_uri);
1239 
1240 	g_object_unref (query);
1241 }
1242 
1243 static void
test_query_dates(void)1244 test_query_dates (void)
1245 {
1246 	GDataQuery *query;
1247 	gchar *query_uri;
1248 
1249 	query = gdata_query_new ("baz");
1250 
1251 	/* updated-min */
1252 	gdata_query_set_updated_min (query, 1373280114); /* 2013-07-08T10:41:54Z */
1253 	query_uri = gdata_query_get_query_uri (query, "http://example.com");
1254 	g_assert_cmpstr (query_uri, ==, "http://example.com?q=baz&updated-min=2013-07-08T10:41:54Z");
1255 	g_free (query_uri);
1256 	gdata_query_set_updated_min (query, -1);
1257 
1258 	/* updated-max */
1259 	gdata_query_set_updated_max (query, 1373280114); /* 2013-07-08T10:41:54Z */
1260 	query_uri = gdata_query_get_query_uri (query, "http://example.com");
1261 	g_assert_cmpstr (query_uri, ==, "http://example.com?q=baz&updated-max=2013-07-08T10:41:54Z");
1262 	g_free (query_uri);
1263 	gdata_query_set_updated_max (query, -1);
1264 
1265 	/* published-min */
1266 	gdata_query_set_published_min (query, 1373280114); /* 2013-07-08T10:41:54Z */
1267 	query_uri = gdata_query_get_query_uri (query, "http://example.com");
1268 	g_assert_cmpstr (query_uri, ==, "http://example.com?q=baz&published-min=2013-07-08T10:41:54Z");
1269 	g_free (query_uri);
1270 	gdata_query_set_published_min (query, -1);
1271 
1272 	/* published-max */
1273 	gdata_query_set_published_max (query, 1373280114); /* 2013-07-08T10:41:54Z */
1274 	query_uri = gdata_query_get_query_uri (query, "http://example.com");
1275 	g_assert_cmpstr (query_uri, ==, "http://example.com?q=baz&published-max=2013-07-08T10:41:54Z");
1276 	g_free (query_uri);
1277 	gdata_query_set_published_max (query, -1);
1278 
1279 	g_object_unref (query);
1280 }
1281 
1282 static void
test_query_strict(void)1283 test_query_strict (void)
1284 {
1285 	GDataQuery *query;
1286 	gchar *query_uri;
1287 
1288 	query = gdata_query_new ("bar");
1289 
1290 	gdata_query_set_is_strict (query, TRUE);
1291 	query_uri = gdata_query_get_query_uri (query, "http://example.com");
1292 	g_assert_cmpstr (query_uri, ==, "http://example.com?q=bar&strict=true");
1293 	g_free (query_uri);
1294 
1295 	gdata_query_set_is_strict (query, FALSE);
1296 	query_uri = gdata_query_get_query_uri (query, "http://example.com");
1297 	g_assert_cmpstr (query_uri, ==, "http://example.com?q=bar");
1298 	g_free (query_uri);
1299 
1300 	g_object_unref (query);
1301 }
1302 
1303 static void
test_query_pagination(void)1304 test_query_pagination (void)
1305 {
1306 	GDataQuery *query;
1307 	gchar *query_uri;
1308 
1309 	query = gdata_query_new ("test");
1310 	gdata_query_set_max_results (query, 15);
1311 	gdata_query_set_etag (query, "etag"); /* this should be cleared by pagination */
1312 
1313 	query_uri = gdata_query_get_query_uri (query, "http://example.com/");
1314 	g_assert_cmpstr (query_uri, ==, "http://example.com/?q=test&max-results=15");
1315 	g_free (query_uri);
1316 
1317 	/* Try the next and previous pages. */
1318 	gdata_query_next_page (query);
1319 	g_assert (gdata_query_get_etag (query) == NULL);
1320 
1321 	query_uri = gdata_query_get_query_uri (query, "http://example.com/");
1322 	g_assert_cmpstr (query_uri, ==, "http://example.com/?q=test&start-index=16&max-results=15");
1323 	g_free (query_uri);
1324 
1325 	gdata_query_set_etag (query, "etag");
1326 	g_assert (gdata_query_previous_page (query) == TRUE);
1327 	g_assert (gdata_query_get_etag (query) == NULL);
1328 
1329 	query_uri = gdata_query_get_query_uri (query, "http://example.com/");
1330 	g_assert_cmpstr (query_uri, ==, "http://example.com/?q=test&max-results=15");
1331 	g_free (query_uri);
1332 
1333 	/* Try another previous page. This should fail, and the ETag should be untouched. */
1334 	gdata_query_set_etag (query, "etag");
1335 	g_assert (gdata_query_previous_page (query) == FALSE);
1336 	g_assert_cmpstr (gdata_query_get_etag (query), ==, "etag");
1337 
1338 	g_object_unref (query);
1339 
1340 	/* Try the alternate constructor. */
1341 	query = gdata_query_new_with_limits ("test", 40, 10);
1342 
1343 	query_uri = gdata_query_get_query_uri (query, "http://example.com/");
1344 	g_assert_cmpstr (query_uri, ==, "http://example.com/?q=test&start-index=40&max-results=10");
1345 	g_free (query_uri);
1346 
1347 	/* Try the next and previous pages again. */
1348 	gdata_query_next_page (query);
1349 
1350 	query_uri = gdata_query_get_query_uri (query, "http://example.com/");
1351 	g_assert_cmpstr (query_uri, ==, "http://example.com/?q=test&start-index=50&max-results=10");
1352 	g_free (query_uri);
1353 
1354 	g_assert (gdata_query_previous_page (query) == TRUE);
1355 
1356 	query_uri = gdata_query_get_query_uri (query, "http://example.com/");
1357 	g_assert_cmpstr (query_uri, ==, "http://example.com/?q=test&start-index=40&max-results=10");
1358 	g_free (query_uri);
1359 
1360 	g_assert (gdata_query_previous_page (query) == TRUE);
1361 
1362 	query_uri = gdata_query_get_query_uri (query, "http://example.com/");
1363 	g_assert_cmpstr (query_uri, ==, "http://example.com/?q=test&start-index=30&max-results=10");
1364 	g_free (query_uri);
1365 
1366 	g_object_unref (query);
1367 }
1368 
1369 static void
notify_cb(GObject * obj,GParamSpec * pspec,gpointer user_data)1370 notify_cb (GObject *obj, GParamSpec *pspec, gpointer user_data)
1371 {
1372 	gboolean *notification_received = user_data;
1373 	g_assert (*notification_received == FALSE);
1374 	*notification_received = TRUE;
1375 }
1376 
1377 static void
test_query_properties(void)1378 test_query_properties (void)
1379 {
1380 	GDataQuery *query;
1381 	gboolean notification_received = FALSE;
1382 	gulong handler_id;
1383 
1384 	query = gdata_query_new ("default");
1385 
1386 #define CHECK_PROPERTY(cmptype, name_hyphens, name_underscores, default_val, new_val, new_val2, val_type, free_val) \
1387 	{ \
1388 		val_type val; \
1389  \
1390 		handler_id = g_signal_connect (query, "notify::" name_hyphens, (GCallback) notify_cb, &notification_received); \
1391  \
1392 		g_assert_##cmptype (gdata_query_get_##name_underscores (query), ==, default_val); \
1393 		g_object_get (query, name_hyphens, &val, NULL); \
1394 		g_assert_##cmptype (val, ==, default_val); \
1395 		if (free_val == TRUE) { \
1396 			g_free ((gpointer) ((guintptr) val)); \
1397 		} \
1398  \
1399 		notification_received = FALSE; \
1400 		gdata_query_set_##name_underscores (query, new_val); \
1401 		g_assert (notification_received == TRUE); \
1402  \
1403 		g_assert_##cmptype (gdata_query_get_##name_underscores (query), ==, new_val); \
1404  \
1405 		notification_received = FALSE; \
1406 		g_object_set (query, name_hyphens, (val_type) new_val2, NULL); \
1407 		g_assert (notification_received == TRUE); \
1408  \
1409 		g_assert_##cmptype (gdata_query_get_##name_underscores (query), ==, new_val2); \
1410  \
1411 		g_signal_handler_disconnect (query, handler_id); \
1412 	}
1413 #define CHECK_PROPERTY_STR(name_hyphens, name_underscores, default_val) \
1414 	CHECK_PROPERTY (cmpstr, name_hyphens, name_underscores, default_val, "new", "new2", gchar*, TRUE)
1415 #define CHECK_PROPERTY_INT64(name_hyphens, name_underscores, default_val) \
1416 	CHECK_PROPERTY (cmpint, name_hyphens, name_underscores, default_val, 123, 5134132, gint64, FALSE)
1417 #define CHECK_PROPERTY_UINT(name_hyphens, name_underscores, default_val) \
1418 	CHECK_PROPERTY (cmpuint, name_hyphens, name_underscores, default_val, 535, 123, guint, FALSE)
1419 #define CHECK_PROPERTY_BOOLEAN(name_hyphens, name_underscores, default_val) \
1420 	CHECK_PROPERTY (cmpuint, name_hyphens, name_underscores, default_val, TRUE, FALSE, gboolean, FALSE)
1421 
1422 	CHECK_PROPERTY_STR ("q", q, "default");
1423 	CHECK_PROPERTY_STR ("categories", categories, NULL);
1424 	CHECK_PROPERTY_STR ("author", author, NULL);
1425 	CHECK_PROPERTY_INT64 ("updated-min", updated_min, -1);
1426 	CHECK_PROPERTY_INT64 ("updated-max", updated_max, -1);
1427 	CHECK_PROPERTY_INT64 ("published-min", published_min, -1);
1428 	CHECK_PROPERTY_INT64 ("published-max", published_max, -1);
1429 	CHECK_PROPERTY_UINT ("start-index", start_index, 0);
1430 #define gdata_query_get_is_strict gdata_query_is_strict
1431 	CHECK_PROPERTY_BOOLEAN ("is-strict", is_strict, FALSE);
1432 #undef gdata_query_get_is_strict
1433 	CHECK_PROPERTY_UINT ("max-results", max_results, 0);
1434 	CHECK_PROPERTY_STR ("etag", etag, NULL);
1435 
1436 #undef CHECK_PROPERTY_BOOLEAN
1437 #undef CHECK_PROPERTY_UINT
1438 #undef CHECK_PROPERTY_INT64
1439 #undef CHECK_PROPERTY_STR
1440 #undef CHECK_PROPERTY
1441 
1442 	g_object_unref (query);
1443 }
1444 
1445 static void
test_query_unicode(void)1446 test_query_unicode (void)
1447 {
1448 	GDataQuery *query;
1449 	gchar *query_uri;
1450 
1451 	g_test_bug ("602497");
1452 
1453 	/* Simple query */
1454 	query = gdata_query_new ("fööbar‽");
1455 	query_uri = gdata_query_get_query_uri (query, "http://example.com");
1456 	g_assert_cmpstr (query_uri, ==, "http://example.com?q=f%C3%B6%C3%B6bar%E2%80%BD");
1457 	g_free (query_uri);
1458 
1459 	/* Categories */
1460 	gdata_query_set_categories (query, "Ümlauts|¿Questions‽");
1461 	query_uri = gdata_query_get_query_uri (query, "http://example.com");
1462 	g_assert_cmpstr (query_uri, ==, "http://example.com/-/%C3%9Cmlauts%7C%C2%BFQuestions%E2%80%BD?q=f%C3%B6%C3%B6bar%E2%80%BD");
1463 	g_free (query_uri);
1464 
1465 	/* Author */
1466 	gdata_query_set_author (query, "Lørd Brïan Bleßêd");
1467 	query_uri = gdata_query_get_query_uri (query, "http://example.com");
1468 	g_assert_cmpstr (query_uri, ==, "http://example.com/-/%C3%9Cmlauts%7C%C2%BFQuestions%E2%80%BD?q=f%C3%B6%C3%B6bar%E2%80%BD&author=L%C3%B8rd%20Br%C3%AFan%20Ble%C3%9F%C3%AAd");
1469 	g_free (query_uri);
1470 
1471 	g_object_unref (query);
1472 }
1473 
1474 static void
test_query_etag(void)1475 test_query_etag (void)
1476 {
1477 	GDataQuery *query = gdata_query_new (NULL);
1478 
1479 	/* Test that setting any property will unset the ETag */
1480 	g_test_bug ("613529");
1481 
1482 	/* Also check that setting the ETag doesn't unset the ETag! */
1483 	gdata_query_set_etag (query, "foobar");
1484 	g_assert_cmpstr (gdata_query_get_etag (query), ==, "foobar");
1485 
1486 #define CHECK_ETAG(C) \
1487 	gdata_query_set_etag (query, "foobar");		\
1488 	C;						\
1489 	g_assert (gdata_query_get_etag (query) == NULL);
1490 
1491 	CHECK_ETAG (gdata_query_set_q (query, "q"))
1492 	CHECK_ETAG (gdata_query_set_categories (query, "shizzle,foobar"))
1493 	CHECK_ETAG (gdata_query_set_author (query, "John Smith"))
1494 	CHECK_ETAG (gdata_query_set_updated_min (query, -1))
1495 	CHECK_ETAG (gdata_query_set_updated_max (query, -1))
1496 	CHECK_ETAG (gdata_query_set_published_min (query, -1))
1497 	CHECK_ETAG (gdata_query_set_published_max (query, -1))
1498 	CHECK_ETAG (gdata_query_set_start_index (query, 5))
1499 	CHECK_ETAG (gdata_query_set_is_strict (query, TRUE))
1500 	CHECK_ETAG (gdata_query_set_max_results (query, 1000))
1501 	CHECK_ETAG (gdata_query_next_page (query))
1502 	CHECK_ETAG (g_assert (gdata_query_previous_page (query)))
1503 
1504 #undef CHECK_ETAG
1505 
1506 	g_object_unref (query);
1507 }
1508 
1509 static void
test_service_network_error(void)1510 test_service_network_error (void)
1511 {
1512 	GDataService *service;
1513 #if 0
1514 	SoupURI *proxy_uri;
1515 #endif
1516 	GError *error = NULL;
1517 
1518 	/* Skip this test unless explicitly asked for, so that we don’t do network accesses on build machines by default. */
1519 	if (!g_test_slow ()) {
1520 		g_test_skip ("Test requires network access");
1521 		return;
1522 	}
1523 
1524 	/* This is a little hacky, but it should work */
1525 	service = g_object_new (GDATA_TYPE_SERVICE, NULL);
1526 
1527 	/* Try a query which should always fail due to errors resolving the hostname */
1528 	g_assert (gdata_service_query (service, NULL, "https://thisshouldnotexist.invalid", NULL, GDATA_TYPE_ENTRY,
1529 	                               NULL, NULL, NULL, &error) == NULL);
1530 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_NETWORK_ERROR);
1531 	g_clear_error (&error);
1532 
1533 	/* TODO: We have to disable this test, as libsoup 2.30.2 < x <= 2.32.0 doesn't return SOUP_STATUS_CANT_RESOLVE_PROXY properly any more.
1534 	 * Filed as bgo#632354. */
1535 #if 0
1536 	/* Try one with a bad proxy set */
1537 	proxy_uri = soup_uri_new ("https://thisshouldalsonotexist.invalid/proxy");
1538 	gdata_service_set_proxy_uri (service, proxy_uri);
1539 	soup_uri_free (proxy_uri);
1540 
1541 	g_assert (gdata_service_query (service, "https://google.com", NULL, GDATA_TYPE_ENTRY, NULL, NULL, NULL, &error) == NULL);
1542 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROXY_ERROR);
1543 	g_clear_error (&error);
1544 #endif
1545 
1546 	g_object_unref (service);
1547 }
1548 
1549 static void
test_service_locale(void)1550 test_service_locale (void)
1551 {
1552 	GDataService *service;
1553 	gchar *locale;
1554 
1555 	/* This is a little hacky, but it should work */
1556 	service = g_object_new (GDATA_TYPE_SERVICE, NULL);
1557 
1558 	/* Just test setting and getting the locale */
1559 	g_assert (gdata_service_get_locale (service) == NULL);
1560 	gdata_service_set_locale (service, "en_GB");
1561 	g_assert_cmpstr (gdata_service_get_locale (service), ==, "en_GB");
1562 
1563 	g_object_get (service, "locale", &locale, NULL);
1564 	g_assert_cmpstr (locale, ==, "en_GB");
1565 	g_free (locale);
1566 
1567 	g_object_unref (service);
1568 }
1569 
1570 static void
test_access_rule_get_xml(void)1571 test_access_rule_get_xml (void)
1572 {
1573 	GDataAccessRule *rule, *rule2;
1574 	const gchar *content_type;
1575 	gchar *xml, *role, *scope_type3, *scope_value3, *key;
1576 	gint64 edited, edited2;
1577 	const gchar *scope_type, *scope_value, *scope_type2, *scope_value2;
1578 	GError *error = NULL;
1579 
1580 	rule = gdata_access_rule_new ("an-id");
1581 
1582 	/* Test setting properties directly */
1583 	g_object_set (G_OBJECT (rule),
1584 	              "role", "A role",
1585 	              "scope-type", "A scope type",
1586 	              "scope-value", "A scope value",
1587 	              NULL);
1588 
1589 	g_assert_cmpstr (gdata_access_rule_get_role (rule), ==, "A role");
1590 	gdata_access_rule_get_scope (rule, &scope_type, &scope_value);
1591 	g_assert_cmpstr (scope_type, ==, "A scope type");
1592 	g_assert_cmpstr (scope_value, ==, "A scope value");
1593 	edited = gdata_access_rule_get_edited (rule);
1594 	g_assert_cmpuint (edited, >, 0); /* current time */
1595 	g_assert_cmpstr (gdata_access_rule_get_key (rule), ==, NULL);
1596 
1597 	/* Set the properties more conventionally */
1598 	gdata_access_rule_set_role (rule, GDATA_ACCESS_ROLE_NONE);
1599 	gdata_access_rule_set_scope (rule, GDATA_ACCESS_SCOPE_USER, "foo@example.com");
1600 
1601 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (rule));
1602 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
1603 
1604 	/* Check the generated XML's OK */
1605 	gdata_test_assert_xml (rule,
1606 			 "<?xml version='1.0' encoding='UTF-8'?>"
1607 			 "<entry xmlns='http://www.w3.org/2005/Atom' "
1608 			 "xmlns:gd='http://schemas.google.com/g/2005' "
1609 			 "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
1610 				"<title type='text'>none</title>"
1611 				"<id>an-id</id>"
1612 				"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
1613 				"<gAcl:role value='none'/>"
1614 				"<gAcl:scope type='user' value='foo@example.com'/>"
1615 			 "</entry>");
1616 
1617 	/* Check again by re-parsing the XML to a GDataAccessRule */
1618 	xml = gdata_parsable_get_xml (GDATA_PARSABLE (rule));
1619 	rule2 = GDATA_ACCESS_RULE (gdata_parsable_new_from_xml (GDATA_TYPE_ACCESS_RULE, xml, -1, &error));
1620 	g_assert_no_error (error);
1621 	g_assert (GDATA_IS_ACCESS_RULE (rule2));
1622 	g_clear_error (&error);
1623 	g_free (xml);
1624 
1625 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (rule2));
1626 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
1627 
1628 	g_assert_cmpstr (gdata_access_rule_get_role (rule), ==, gdata_access_rule_get_role (rule2));
1629 	gdata_access_rule_get_scope (rule, &scope_type, &scope_value);
1630 	gdata_access_rule_get_scope (rule2, &scope_type2, &scope_value2);
1631 	g_assert_cmpstr (scope_type, ==, scope_type2);
1632 	g_assert_cmpstr (scope_value, ==, scope_value2);
1633 	edited = gdata_access_rule_get_edited (rule2);
1634 	g_assert_cmpuint (edited, ==, -1); /* unspecified in XML */
1635 	g_assert_cmpstr (gdata_access_rule_get_key (rule), ==, gdata_access_rule_get_key (rule2));
1636 
1637 	/* Check properties a different way */
1638 	g_object_get (G_OBJECT (rule2),
1639 	              "role", &role,
1640 	              "scope-type", &scope_type3,
1641 	              "scope-value", &scope_value3,
1642 	              "edited", &edited2,
1643 	              "key", &key,
1644 	              NULL);
1645 
1646 	g_assert_cmpstr (role, ==, gdata_access_rule_get_role (rule));
1647 	g_assert_cmpstr (scope_type, ==, scope_type3);
1648 	g_assert_cmpstr (scope_value, ==, scope_value3);
1649 	g_assert_cmpuint (edited2, ==, -1);
1650 	g_assert_cmpstr (key, ==, NULL);
1651 
1652 	g_free (role);
1653 	g_free (scope_type3);
1654 	g_free (scope_value3);
1655 
1656 	/* Test that the GDataAccessRule:role and GDataEntry:title properties are linked */
1657 	gdata_entry_set_title (GDATA_ENTRY (rule), "Another role");
1658 	g_assert_cmpstr (gdata_access_rule_get_role (rule), ==, "Another role");
1659 	gdata_access_rule_set_role (rule, GDATA_ACCESS_ROLE_NONE);
1660 	g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (rule)), ==, "none");
1661 
1662 	g_object_unref (rule);
1663 	g_object_unref (rule2);
1664 
1665 	/* Check that a rule with scope type 'default' doesn't have a value.
1666 	 * See: https://developers.google.com/google-apps/calendar/v2/reference#gacl_reference */
1667 	rule = gdata_access_rule_new ("another-id");
1668 	gdata_access_rule_set_role (rule, GDATA_ACCESS_ROLE_NONE);
1669 	gdata_access_rule_set_scope (rule, GDATA_ACCESS_SCOPE_DEFAULT, NULL);
1670 
1671 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (rule));
1672 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
1673 
1674 	/* Check the generated XML's OK */
1675 	gdata_test_assert_xml (rule,
1676 		"<?xml version='1.0' encoding='UTF-8'?>"
1677 		"<entry xmlns='http://www.w3.org/2005/Atom' "
1678 		       "xmlns:gd='http://schemas.google.com/g/2005' "
1679 		       "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
1680 			"<title type='text'>none</title>"
1681 			"<id>another-id</id>"
1682 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
1683 			"<gAcl:role value='none'/>"
1684 			"<gAcl:scope type='default'/>"
1685 		"</entry>");
1686 
1687 	/* Check by re-parsing the XML to a GDataAccessRule */
1688 	xml = gdata_parsable_get_xml (GDATA_PARSABLE (rule));
1689 	rule2 = GDATA_ACCESS_RULE (gdata_parsable_new_from_xml (GDATA_TYPE_ACCESS_RULE, xml, -1, &error));
1690 	g_assert_no_error (error);
1691 	g_assert (GDATA_IS_ACCESS_RULE (rule2));
1692 	g_clear_error (&error);
1693 	g_free (xml);
1694 
1695 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (rule2));
1696 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
1697 
1698 	g_assert_cmpstr (gdata_access_rule_get_role (rule), ==, gdata_access_rule_get_role (rule2));
1699 	gdata_access_rule_get_scope (rule, &scope_type, &scope_value);
1700 	gdata_access_rule_get_scope (rule2, &scope_type2, &scope_value2);
1701 	g_assert_cmpstr (scope_type, ==, scope_type2);
1702 	g_assert_cmpstr (scope_value, ==, scope_value2);
1703 	edited = gdata_access_rule_get_edited (rule2);
1704 	g_assert_cmpuint (edited, ==, -1); /* unspecified in XML */
1705 
1706 	g_object_unref (rule);
1707 	g_object_unref (rule2);
1708 }
1709 
1710 static void
test_access_rule_get_xml_with_key(void)1711 test_access_rule_get_xml_with_key (void)
1712 {
1713 	GDataAccessRule *rule;
1714 	gint64 edited;
1715 	const gchar *content_type, *scope_type, *scope_value;
1716 	GError *error = NULL;
1717 
1718 	rule = GDATA_ACCESS_RULE (gdata_parsable_new_from_xml (GDATA_TYPE_ACCESS_RULE,
1719 		"<?xml version='1.0' encoding='UTF-8'?>"
1720 		"<entry xmlns='http://www.w3.org/2005/Atom' "
1721 		       "xmlns:gd='http://schemas.google.com/g/2005' "
1722 		       "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
1723 			"<title type='text'>none</title>"
1724 			"<id>an-id</id>"
1725 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
1726 			"<gAcl:withKey key='asdasd'><gAcl:role value='none'/></gAcl:withKey>"
1727 			"<gAcl:scope type='user' value='foo@example.com'/>"
1728 		"</entry>", -1, &error));
1729 	g_assert_no_error (error);
1730 	g_assert (GDATA_IS_ACCESS_RULE (rule));
1731 
1732 	/* Check the properties. */
1733 	g_assert_cmpstr (gdata_access_rule_get_role (rule), ==, "none");
1734 	gdata_access_rule_get_scope (rule, &scope_type, &scope_value);
1735 	g_assert_cmpstr (scope_type, ==, "user");
1736 	g_assert_cmpstr (scope_value, ==, "foo@example.com");
1737 	edited = gdata_access_rule_get_edited (rule);
1738 	g_assert_cmpuint (edited, >, 0); /* current time */
1739 	g_assert_cmpstr (gdata_access_rule_get_key (rule), ==, "asdasd");
1740 
1741 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (rule));
1742 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
1743 
1744 	/* Check the outputted XML is the same. */
1745 	gdata_test_assert_xml (rule,
1746 		"<?xml version='1.0' encoding='UTF-8'?>"
1747 		"<entry xmlns='http://www.w3.org/2005/Atom' "
1748 		       "xmlns:gd='http://schemas.google.com/g/2005' "
1749 		       "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
1750 			"<title type='text'>none</title>"
1751 			"<id>an-id</id>"
1752 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
1753 			"<gAcl:withKey key='asdasd'><gAcl:role value='none'/></gAcl:withKey>"
1754 			"<gAcl:scope type='user' value='foo@example.com'/>"
1755 		"</entry>");
1756 
1757 	g_object_unref (rule);
1758 }
1759 
1760 static void
test_access_rule_error_handling(void)1761 test_access_rule_error_handling (void)
1762 {
1763 	GDataAccessRule *rule;
1764 	GError *error = NULL;
1765 
1766 #define TEST_XML_ERROR_HANDLING(x) rule = GDATA_ACCESS_RULE (gdata_parsable_new_from_xml (GDATA_TYPE_ACCESS_RULE,\
1767 		"<entry xmlns='http://www.w3.org/2005/Atom' xmlns:app='http://www.w3.org/2007/app' xmlns:gAcl='http://schemas.google.com/acl/2007'>"\
1768 			x\
1769 		"</entry>", -1, &error));\
1770 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);\
1771 	g_assert (rule == NULL);\
1772 	g_clear_error (&error)
1773 
1774 	/* role */
1775 	TEST_XML_ERROR_HANDLING ("<gAcl:role/>"); /* missing value */
1776 
1777 	/* scope */
1778 	TEST_XML_ERROR_HANDLING ("<gAcl:scope/>"); /* missing type */
1779 	TEST_XML_ERROR_HANDLING ("<gAcl:scope type='user'/>"); /* missing value */
1780 	TEST_XML_ERROR_HANDLING ("<gAcl:scope type='domain'/>"); /* missing value */
1781 
1782 	/* edited */
1783 	TEST_XML_ERROR_HANDLING ("<app:edited/>"); /* missing date */
1784 	TEST_XML_ERROR_HANDLING ("<app:edited>not a date</app:edited>"); /* bad date */
1785 
1786 	/* withKey */
1787 	TEST_XML_ERROR_HANDLING ("<gAcl:withKey><gAcl:role value='none'/></gAcl:withKey>");  /* missing key */
1788 	TEST_XML_ERROR_HANDLING ("<gAcl:withKey key='asd'/>");  /* missing role */
1789 	TEST_XML_ERROR_HANDLING ("<gAcl:withKey key='asd'><gAcl:role/></gAcl:withKey>");  /* missing role */
1790 
1791 #undef TEST_XML_ERROR_HANDLING
1792 }
1793 
1794 static void
test_access_rule_escaping(void)1795 test_access_rule_escaping (void)
1796 {
1797 	GDataAccessRule *rule;
1798 
1799 	rule = gdata_access_rule_new (NULL);
1800 	gdata_access_rule_set_role (rule, "<role>");
1801 	gdata_access_rule_set_scope (rule, "<scope>", "<value>");
1802 
1803 	/* Check the outputted XML is escaped properly */
1804 	gdata_test_assert_xml (rule,
1805 		"<?xml version='1.0' encoding='UTF-8'?>"
1806 		"<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
1807 		       "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
1808 			"<title type='text'>&lt;role&gt;</title>"
1809 			"<category term='http://schemas.google.com/acl/2007#accessRule' scheme='http://schemas.google.com/g/2005#kind'/>"
1810 			"<gAcl:role value='&lt;role&gt;'/>"
1811 			"<gAcl:scope type='&lt;scope&gt;' value='&lt;value&gt;'/>"
1812 		"</entry>");
1813 	g_object_unref (rule);
1814 }
1815 
1816 static void
test_comparable(void)1817 test_comparable (void)
1818 {
1819 	GDataComparable *category = GDATA_COMPARABLE (gdata_category_new ("term", "http://scheme", "label"));
1820 
1821 	/* Test the NULL comparisons */
1822 	g_assert_cmpint (gdata_comparable_compare (category, NULL), ==, 1);
1823 	g_assert_cmpint (gdata_comparable_compare (NULL, category), ==, -1);
1824 	g_assert_cmpint (gdata_comparable_compare (NULL, NULL), ==, 0);
1825 	g_assert_cmpint (gdata_comparable_compare (category, category), ==, 0);
1826 
1827 	g_object_unref (category);
1828 }
1829 
1830 static void
test_color_parsing(void)1831 test_color_parsing (void)
1832 {
1833 	GDataColor color;
1834 
1835 	/* With hash */
1836 	g_assert (gdata_color_from_hexadecimal ("#F99Ff0", &color) == TRUE);
1837 	g_assert_cmpuint (color.red, ==, 249);
1838 	g_assert_cmpuint (color.green, ==, 159);
1839 	g_assert_cmpuint (color.blue, ==, 240);
1840 
1841 	/* Without hash */
1842 	g_assert (gdata_color_from_hexadecimal ("F99Ff0", &color) == TRUE);
1843 	g_assert_cmpuint (color.red, ==, 249);
1844 	g_assert_cmpuint (color.green, ==, 159);
1845 	g_assert_cmpuint (color.blue, ==, 240);
1846 
1847 	/* Invalid, but correct length */
1848 	g_assert (gdata_color_from_hexadecimal ("foobar", &color) == FALSE);
1849 
1850 	/* Wildly invalid */
1851 	g_assert (gdata_color_from_hexadecimal ("this is not a real colour!", &color) == FALSE);
1852 }
1853 
1854 static void
test_color_output(void)1855 test_color_output (void)
1856 {
1857 	GDataColor color;
1858 	gchar *color_string;
1859 
1860 	/* General test */
1861 	g_assert (gdata_color_from_hexadecimal ("#F99Ff0", &color) == TRUE);
1862 	color_string = gdata_color_to_hexadecimal (&color);
1863 	g_assert_cmpstr (color_string, ==, "#f99ff0");
1864 	g_free (color_string);
1865 
1866 	/* Boundary tests */
1867 	g_assert (gdata_color_from_hexadecimal ("#ffffff", &color) == TRUE);
1868 	color_string = gdata_color_to_hexadecimal (&color);
1869 	g_assert_cmpstr (color_string, ==, "#ffffff");
1870 	g_free (color_string);
1871 
1872 	g_assert (gdata_color_from_hexadecimal ("#000000", &color) == TRUE);
1873 	color_string = gdata_color_to_hexadecimal (&color);
1874 	g_assert_cmpstr (color_string, ==, "#000000");
1875 	g_free (color_string);
1876 }
1877 
1878 /*static void
1879 test_media_thumbnail_parse_time (const gchar *locale)
1880 {
1881 	g_test_bug ("584737");
1882 
1883 	g_test_message ("Testing gdata_media_thumbnail_parse_time in the \"%s\" locale...", locale);
1884 	g_assert_cmpstr (setlocale (LC_ALL, locale), ==, locale);
1885 
1886 	g_assert_cmpint (gdata_media_thumbnail_parse_time ("00:01:42.500"), ==, 102500);
1887 	g_assert_cmpint (gdata_media_thumbnail_parse_time ("00:02:45"), ==, 165000);
1888 	g_assert_cmpint (gdata_media_thumbnail_parse_time ("12:00:15.000"), ==, 43215000);
1889 	g_assert_cmpint (gdata_media_thumbnail_parse_time ("00:00:00"), ==, 0);
1890 	g_assert_cmpint (gdata_media_thumbnail_parse_time ("foobar"), ==, -1);
1891 
1892 	setlocale (LC_ALL, "");
1893 }*/
1894 
1895 static void
test_atom_author(void)1896 test_atom_author (void)
1897 {
1898 	GDataAuthor *author, *author2;
1899 	const gchar *content_type;
1900 	gchar *name, *uri, *email_address;
1901 	GError *error = NULL;
1902 
1903 	author = GDATA_AUTHOR (gdata_parsable_new_from_xml (GDATA_TYPE_AUTHOR,
1904 		"<author>"
1905 			"<name>John Smöth</name>"
1906 			"<uri>http://example.com/</uri>"
1907 			"<email>john@example.com</email>"
1908 		"</author>", -1, &error));
1909 	g_assert_no_error (error);
1910 	g_assert (GDATA_IS_AUTHOR (author));
1911 	g_clear_error (&error);
1912 
1913 	/* Check the properties */
1914 	g_assert_cmpstr (gdata_author_get_name (author), ==, "John Smöth");
1915 	g_assert_cmpstr (gdata_author_get_uri (author), ==, "http://example.com/");
1916 	g_assert_cmpstr (gdata_author_get_email_address (author), ==, "john@example.com");
1917 
1918 	/* Compare it against another identical author */
1919 	author2 = gdata_author_new ("John Smöth", "http://example.com/", "john@example.com");
1920 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (author), GDATA_COMPARABLE (author2)), ==, 0);
1921 	g_object_unref (author2);
1922 
1923 	/* …and a different author */
1924 	author2 = gdata_author_new ("Brian Blessed", NULL, NULL);
1925 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (author), GDATA_COMPARABLE (author2)), !=, 0);
1926 	g_object_unref (author2);
1927 
1928 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (author));
1929 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
1930 
1931 	/* Check the outputted XML is the same */
1932 	gdata_test_assert_xml (author,
1933 			 "<?xml version='1.0' encoding='UTF-8'?>"
1934 			 "<author xmlns='http://www.w3.org/2005/Atom'>"
1935 				"<name>John Smöth</name>"
1936 				"<uri>http://example.com/</uri>"
1937 				"<email>john@example.com</email>"
1938 			 "</author>");
1939 
1940 	/* Check the properties */
1941 	g_object_get (G_OBJECT (author),
1942 	              "name", &name,
1943 	              "uri", &uri,
1944 	              "email-address", &email_address,
1945 	              NULL);
1946 
1947 	g_assert_cmpstr (name, ==, "John Smöth");
1948 	g_assert_cmpstr (uri, ==, "http://example.com/");
1949 	g_assert_cmpstr (email_address, ==, "john@example.com");
1950 
1951 	g_free (name);
1952 	g_free (uri);
1953 	g_free (email_address);
1954 	g_object_unref (author);
1955 
1956 	/* Now parse an author with little information available */
1957 	author = GDATA_AUTHOR (gdata_parsable_new_from_xml (GDATA_TYPE_AUTHOR,
1958 		"<author>"
1959 			"<name>James Johnson</name>"
1960 		"</author>", -1, &error));
1961 	g_assert_no_error (error);
1962 	g_assert (GDATA_IS_AUTHOR (author));
1963 	g_clear_error (&error);
1964 
1965 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (author));
1966 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
1967 
1968 	/* Check the properties */
1969 	g_assert_cmpstr (gdata_author_get_name (author), ==, "James Johnson");
1970 	g_assert (gdata_author_get_uri (author) == NULL);
1971 	g_assert (gdata_author_get_email_address (author) == NULL);
1972 
1973 	g_object_unref (author);
1974 }
1975 
1976 static void
test_atom_author_error_handling(void)1977 test_atom_author_error_handling (void)
1978 {
1979 	GDataAuthor *author;
1980 	GError *error = NULL;
1981 
1982 #define TEST_XML_ERROR_HANDLING(x) author = GDATA_AUTHOR (gdata_parsable_new_from_xml (GDATA_TYPE_AUTHOR,\
1983 		"<author>"\
1984 			x\
1985 		"</author>", -1, &error));\
1986 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);\
1987 	g_assert (author == NULL);\
1988 	g_clear_error (&error)
1989 
1990 	/* name */
1991 	TEST_XML_ERROR_HANDLING ("<name>John Smöth</name><name>Not John Smöth</name>"); /* duplicated name */
1992 	TEST_XML_ERROR_HANDLING ("<name></name>"); /* empty name */
1993 	TEST_XML_ERROR_HANDLING ("<uri>http://example.com/</uri><email>john@example.com</email>"); /* missing name */
1994 
1995 	/* uri */
1996 	TEST_XML_ERROR_HANDLING ("<uri>http://example.com/</uri><uri>http://another-example.com/</uri>"); /* duplicated URI */
1997 
1998 	/* email */
1999 	TEST_XML_ERROR_HANDLING ("<email>john@example.com</email><email>john@another-example.com</email>"); /* duplicated e-mail address */
2000 
2001 #undef TEST_XML_ERROR_HANDLING
2002 }
2003 
2004 static void
test_atom_author_escaping(void)2005 test_atom_author_escaping (void)
2006 {
2007 	GDataAuthor *author;
2008 
2009 	author = gdata_author_new ("First & Last Name", "http://foo.com?foo&bar", "John Smith <john.smith@gmail.com>");
2010 
2011 	/* Check the outputted XML is escaped properly */
2012 	gdata_test_assert_xml (author,
2013 	                 "<?xml version='1.0' encoding='UTF-8'?>"
2014 	                 "<author xmlns='http://www.w3.org/2005/Atom'>"
2015 				"<name>First &amp; Last Name</name>"
2016 				"<uri>http://foo.com?foo&amp;bar</uri>"
2017 				"<email>John Smith &lt;john.smith@gmail.com&gt;</email>"
2018 	                 "</author>");
2019 	g_object_unref (author);
2020 }
2021 
2022 static void
test_atom_category(void)2023 test_atom_category (void)
2024 {
2025 	GDataCategory *category, *category2;
2026 	const gchar *content_type;
2027 	gchar *term, *scheme, *label;
2028 	GError *error = NULL;
2029 
2030 	category = GDATA_CATEGORY (gdata_parsable_new_from_xml (GDATA_TYPE_CATEGORY,
2031 		"<category term='jokes' scheme='http://foobar.com#categories' label='Jokes &amp; Trivia'/>", -1, &error));
2032 	g_assert_no_error (error);
2033 	g_assert (GDATA_IS_CATEGORY (category));
2034 	g_clear_error (&error);
2035 
2036 	/* Check the properties */
2037 	g_assert_cmpstr (gdata_category_get_term (category), ==, "jokes");
2038 	g_assert_cmpstr (gdata_category_get_scheme (category), ==, "http://foobar.com#categories");
2039 	g_assert_cmpstr (gdata_category_get_label (category), ==, "Jokes & Trivia");
2040 
2041 	/* Compare it against another identical category */
2042 	category2 = gdata_category_new ("jokes", "http://foobar.com#categories", "Jokes & Trivia");
2043 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (category), GDATA_COMPARABLE (category2)), ==, 0);
2044 	g_object_unref (category2);
2045 
2046 	/* …and a different category */
2047 	category2 = gdata_category_new ("sports", "http://foobar.com#categories", NULL);
2048 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (category), GDATA_COMPARABLE (category2)), !=, 0);
2049 	g_object_unref (category2);
2050 
2051 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (category));
2052 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
2053 
2054 	/* Check the outputted XML is the same */
2055 	gdata_test_assert_xml (category,
2056 			 "<?xml version='1.0' encoding='UTF-8'?>"
2057 			 "<category xmlns='http://www.w3.org/2005/Atom' "
2058 				"term='jokes' scheme='http://foobar.com#categories' label='Jokes &amp; Trivia'/>");
2059 
2060 	/* Check the properties */
2061 	g_object_get (G_OBJECT (category),
2062 	              "term", &term,
2063 	              "scheme", &scheme,
2064 	              "label", &label,
2065 	              NULL);
2066 
2067 	g_assert_cmpstr (term, ==, "jokes");
2068 	g_assert_cmpstr (scheme, ==, "http://foobar.com#categories");
2069 	g_assert_cmpstr (label, ==, "Jokes & Trivia");
2070 
2071 	g_free (term);
2072 	g_free (scheme);
2073 	g_free (label);
2074 	g_object_unref (category);
2075 
2076 	/* Now parse a category with less information available */
2077 	category = GDATA_CATEGORY (gdata_parsable_new_from_xml (GDATA_TYPE_CATEGORY,
2078 		"<category term='sports'/>", -1, &error));
2079 	g_assert_no_error (error);
2080 	g_assert (GDATA_IS_CATEGORY (category));
2081 	g_clear_error (&error);
2082 
2083 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (category));
2084 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
2085 
2086 	/* Check the properties */
2087 	g_assert_cmpstr (gdata_category_get_term (category), ==, "sports");
2088 	g_assert (gdata_category_get_scheme (category) == NULL);
2089 	g_assert (gdata_category_get_label (category) == NULL);
2090 	g_object_unref (category);
2091 
2092 	/* Try a category with custom content */
2093 	category = GDATA_CATEGORY (gdata_parsable_new_from_xml (GDATA_TYPE_CATEGORY,
2094 		"<category term='documentary'>"
2095 			"<foobar/>"
2096 			"<shizzle/>"
2097 		"</category>", -1, &error));
2098 	g_assert_no_error (error);
2099 	g_assert (GDATA_IS_CATEGORY (category));
2100 	g_clear_error (&error);
2101 
2102 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (category));
2103 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
2104 
2105 	/* Check the outputted XML contains the unknown XML */
2106 	gdata_test_assert_xml (category,
2107 			 "<?xml version='1.0' encoding='UTF-8'?>"
2108 			 "<category xmlns='http://www.w3.org/2005/Atom' term='documentary'>"
2109 				"<foobar/>"
2110 				"<shizzle/>"
2111 			 "</category>");
2112 	g_object_unref (category);
2113 }
2114 
2115 static void
test_atom_category_error_handling(void)2116 test_atom_category_error_handling (void)
2117 {
2118 	GDataCategory *category;
2119 	GError *error = NULL;
2120 
2121 	/* Missing term */
2122 	category = GDATA_CATEGORY (gdata_parsable_new_from_xml (GDATA_TYPE_CATEGORY, "<category/>", -1, &error));
2123 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);
2124 	g_assert (category == NULL);
2125 	g_clear_error (&error);
2126 }
2127 
2128 static void
test_atom_category_escaping(void)2129 test_atom_category_escaping (void)
2130 {
2131 	GDataCategory *category;
2132 
2133 	category = gdata_category_new ("<term>", "http://foo.com?foo&bar", "Label & Stuff");
2134 
2135 	/* Check the outputted XML is escaped properly */
2136 	gdata_test_assert_xml (category,
2137 	                 "<?xml version='1.0' encoding='UTF-8'?>"
2138 	                 "<category xmlns='http://www.w3.org/2005/Atom' term='&lt;term&gt;' scheme='http://foo.com?foo&amp;bar' "
2139 				"label='Label &amp; Stuff'/>");
2140 	g_object_unref (category);
2141 }
2142 
2143 static void
test_atom_generator(void)2144 test_atom_generator (void)
2145 {
2146 	GDataGenerator *generator, *generator2;
2147 	const gchar *content_type;
2148 	gchar *name, *uri, *version;
2149 	GError *error = NULL;
2150 
2151 	generator = GDATA_GENERATOR (gdata_parsable_new_from_xml (GDATA_TYPE_GENERATOR,
2152 		"<generator uri='http://example.com/' version='15'>Bach &amp; Son's Generator</generator>", -1, &error));
2153 	g_assert_no_error (error);
2154 	g_assert (GDATA_IS_GENERATOR (generator));
2155 	g_clear_error (&error);
2156 
2157 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (generator));
2158 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
2159 
2160 	/* Compare it against another identical generator */
2161 	generator2 = GDATA_GENERATOR (gdata_parsable_new_from_xml (GDATA_TYPE_GENERATOR,
2162 		"<generator uri='http://example.com/' version='15'>Bach &amp; Son's Generator</generator>", -1, NULL));
2163 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (generator), GDATA_COMPARABLE (generator2)), ==, 0);
2164 	g_object_unref (generator2);
2165 
2166 	/* …and a different generator */
2167 	generator2 = GDATA_GENERATOR (gdata_parsable_new_from_xml (GDATA_TYPE_GENERATOR,
2168 		"<generator>Different generator</generator>", -1, &error));
2169 	g_assert_no_error (error);
2170 	g_assert (GDATA_IS_GENERATOR (generator));
2171 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (generator), GDATA_COMPARABLE (generator2)), !=, 0);
2172 	g_object_unref (generator2);
2173 
2174 	/* Check the properties */
2175 	g_assert_cmpstr (gdata_generator_get_name (generator), ==, "Bach & Son's Generator");
2176 	g_assert_cmpstr (gdata_generator_get_uri (generator), ==, "http://example.com/");
2177 	g_assert_cmpstr (gdata_generator_get_version (generator), ==, "15");
2178 
2179 	/* Check them a different way too */
2180 	g_object_get (G_OBJECT (generator),
2181 	              "name", &name,
2182 	              "uri", &uri,
2183 	              "version", &version,
2184 	              NULL);
2185 
2186 	g_assert_cmpstr (name, ==, "Bach & Son's Generator");
2187 	g_assert_cmpstr (uri, ==, "http://example.com/");
2188 	g_assert_cmpstr (version, ==, "15");
2189 
2190 	g_free (name);
2191 	g_free (uri);
2192 	g_free (version);
2193 	g_object_unref (generator);
2194 
2195 	/* Now parse a generator with less information available */
2196 	generator = GDATA_GENERATOR (gdata_parsable_new_from_xml (GDATA_TYPE_GENERATOR,
2197 		"<generator/>", -1, &error));
2198 	g_assert_no_error (error);
2199 	g_assert (GDATA_IS_GENERATOR (generator));
2200 	g_clear_error (&error);
2201 
2202 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (generator));
2203 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
2204 
2205 	/* Check the properties */
2206 	g_assert (gdata_generator_get_name (generator) == NULL);
2207 	g_assert (gdata_generator_get_uri (generator) == NULL);
2208 	g_assert (gdata_generator_get_version (generator) == NULL);
2209 	g_object_unref (generator);
2210 }
2211 
2212 static void
test_atom_generator_error_handling(void)2213 test_atom_generator_error_handling (void)
2214 {
2215 	GDataGenerator *generator;
2216 	GError *error = NULL;
2217 
2218 	/* Empty URI */
2219 	generator = GDATA_GENERATOR (gdata_parsable_new_from_xml (GDATA_TYPE_GENERATOR, "<generator uri=''/>", -1, &error));
2220 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);
2221 	g_assert (generator == NULL);
2222 	g_clear_error (&error);
2223 }
2224 
2225 static void
test_atom_link(void)2226 test_atom_link (void)
2227 {
2228 	GDataLink *link1, *link2;
2229 	gchar *uri, *relation_type, *content_type, *language, *title;
2230 	gint length;
2231 	GError *error = NULL;
2232 
2233 	link1 = GDATA_LINK (gdata_parsable_new_from_xml (GDATA_TYPE_LINK,
2234 		"<link href='http://example.com/' rel='http://test.com#link-type' type='text/plain' hreflang='de' "
2235 			"title='All About Angle Brackets: &lt;, &gt;' length='2000'/>", -1, &error));
2236 	g_assert_no_error (error);
2237 	g_assert (GDATA_IS_LINK (link1));
2238 	g_clear_error (&error);
2239 
2240 	/* Check the properties */
2241 	g_assert_cmpstr (gdata_link_get_uri (link1), ==, "http://example.com/");
2242 	g_assert_cmpstr (gdata_link_get_relation_type (link1), ==, "http://test.com#link-type");
2243 	g_assert_cmpstr (gdata_link_get_content_type (link1), ==, "text/plain");
2244 	g_assert_cmpstr (gdata_link_get_language (link1), ==, "de");
2245 	g_assert_cmpstr (gdata_link_get_title (link1), ==, "All About Angle Brackets: <, >");
2246 	g_assert_cmpint (gdata_link_get_length (link1), ==, 2000);
2247 
2248 	/* Compare it against another identical link */
2249 	link2 = gdata_link_new ("http://example.com/", "http://test.com#link-type");
2250 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (link1), GDATA_COMPARABLE (link2)), ==, 0);
2251 	gdata_link_set_content_type (link2, "text/plain");
2252 	gdata_link_set_language (link2, "de");
2253 	gdata_link_set_title (link2, "All About Angle Brackets: <, >");
2254 	gdata_link_set_length (link2, 2000);
2255 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (link1), GDATA_COMPARABLE (link2)), ==, 0);
2256 
2257 	/* Try with a dissimilar link */
2258 	gdata_link_set_uri (link2, "http://gnome.org/");
2259 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (link1), GDATA_COMPARABLE (link2)), !=, 0);
2260 	g_object_unref (link2);
2261 
2262 	g_assert_cmpstr (gdata_parsable_get_content_type (GDATA_PARSABLE (link1)), ==, "application/atom+xml");
2263 
2264 	/* Check the outputted XML is the same */
2265 	gdata_test_assert_xml (link1,
2266 			 "<?xml version='1.0' encoding='UTF-8'?>"
2267 			 "<link xmlns='http://www.w3.org/2005/Atom' href='http://example.com/' title='All About Angle Brackets: &lt;, &gt;' "
2268 				"rel='http://test.com#link-type' type='text/plain' hreflang='de' length='2000'/>");
2269 
2270 	/* Set some of the properties */
2271 	g_object_set (G_OBJECT (link1),
2272 	              "uri", "http://another-example.com/",
2273 	              "relation-type", "http://test.com#link-type2",
2274 	              "content-type", "text/html",
2275 	              "language", "sv",
2276 	              "title", "This & That About <Angle Brackets>",
2277 	              "length", -1,
2278 	              NULL);
2279 
2280 	/* Check the properties */
2281 	g_object_get (G_OBJECT (link1),
2282 	              "uri", &uri,
2283 	              "relation-type", &relation_type,
2284 	              "content-type", &content_type,
2285 	              "language", &language,
2286 	              "title", &title,
2287 	              "length", &length,
2288 	              NULL);
2289 
2290 	g_assert_cmpstr (uri, ==, "http://another-example.com/");
2291 	g_assert_cmpstr (relation_type, ==, "http://test.com#link-type2");
2292 	g_assert_cmpstr (content_type, ==, "text/html");
2293 	g_assert_cmpstr (language, ==, "sv");
2294 	g_assert_cmpstr (title, ==, "This & That About <Angle Brackets>");
2295 	g_assert_cmpint (length, ==, -1);
2296 
2297 	g_free (uri);
2298 	g_free (relation_type);
2299 	g_free (content_type);
2300 	g_free (language);
2301 	g_free (title);
2302 	g_object_unref (link1);
2303 
2304 	/* Now parse a link with less information available */
2305 	link1 = GDATA_LINK (gdata_parsable_new_from_xml (GDATA_TYPE_LINK,
2306 		"<link href='http://shizzle.com'>Test Content<foobar/></link>", -1, &error));
2307 	g_assert_no_error (error);
2308 	g_assert (GDATA_IS_LINK (link1));
2309 	g_clear_error (&error);
2310 
2311 	/* Check the properties */
2312 	g_assert_cmpstr (gdata_link_get_uri (link1), ==, "http://shizzle.com");
2313 	g_assert_cmpstr (gdata_link_get_relation_type (link1), ==, "http://www.iana.org/assignments/relation/alternate");
2314 	g_assert (gdata_link_get_content_type (link1) == NULL);
2315 	g_assert (gdata_link_get_language (link1) == NULL);
2316 	g_assert (gdata_link_get_title (link1) == NULL);
2317 	g_assert (gdata_link_get_length (link1) == -1);
2318 
2319 	g_assert_cmpstr (gdata_parsable_get_content_type (GDATA_PARSABLE (link1)), ==, "application/atom+xml");
2320 
2321 	/* Check the outputted XML contains the unknown XML */
2322 	gdata_test_assert_xml (link1,
2323 			 "<?xml version='1.0' encoding='UTF-8'?>"
2324 			 "<link xmlns='http://www.w3.org/2005/Atom' href='http://shizzle.com' rel='http://www.iana.org/assignments/relation/alternate'>"
2325 				"Test Content<foobar/></link>");
2326 	g_object_unref (link1);
2327 }
2328 
2329 static void
test_atom_link_error_handling(void)2330 test_atom_link_error_handling (void)
2331 {
2332 	GDataLink *_link; /* stupid unistd.h */
2333 	GError *error = NULL;
2334 
2335 #define TEST_XML_ERROR_HANDLING(x) _link = GDATA_LINK (gdata_parsable_new_from_xml (GDATA_TYPE_LINK,\
2336 		"<link " x "/>", -1, &error));\
2337 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);\
2338 	g_assert (_link == NULL);\
2339 	g_clear_error (&error)
2340 
2341 	/* href */
2342 	TEST_XML_ERROR_HANDLING (""); /* missing href */
2343 	TEST_XML_ERROR_HANDLING ("href=''"); /* empty href */
2344 
2345 	/* rel */
2346 	TEST_XML_ERROR_HANDLING ("href='http://example.com/' rel=''"); /* empty rel */
2347 
2348 	/* type */
2349 	TEST_XML_ERROR_HANDLING ("href='http://example.com/' type=''"); /* empty type */
2350 
2351 	/* hreflang */
2352 	TEST_XML_ERROR_HANDLING ("href='http://example.com/' hreflang=''"); /* empty hreflang */
2353 
2354 #undef TEST_XML_ERROR_HANDLING
2355 }
2356 
2357 static void
test_atom_link_escaping(void)2358 test_atom_link_escaping (void)
2359 {
2360 	GDataLink *_link;
2361 
2362 	_link = gdata_link_new ("http://foo.com?foo&bar", "http://foo.com?foo&relation=bar");
2363 	gdata_link_set_content_type (_link, "<content type>");
2364 	gdata_link_set_language (_link, "<language>");
2365 	gdata_link_set_title (_link, "Title & stuff");
2366 
2367 
2368 	/* Check the outputted XML is escaped properly */
2369 	gdata_test_assert_xml (_link,
2370 	                 "<?xml version='1.0' encoding='UTF-8'?>"
2371 	                 "<link xmlns='http://www.w3.org/2005/Atom' href='http://foo.com?foo&amp;bar' title='Title &amp; stuff' "
2372 				"rel='http://foo.com?foo&amp;relation=bar' type='&lt;content type&gt;' hreflang='&lt;language&gt;'/>");
2373 	g_object_unref (_link);
2374 }
2375 
2376 static void
test_app_categories(void)2377 test_app_categories (void)
2378 {
2379 	GDataAPPCategories *categories;
2380 	GList *_categories;
2381 	gboolean fixed;
2382 	const gchar *content_type;
2383 	GError *error = NULL;
2384 
2385 	categories = GDATA_APP_CATEGORIES (gdata_parsable_new_from_json (GDATA_TYPE_APP_CATEGORIES,
2386 		"{"
2387 			"'kind': 'youtube#videoCategoryListResponse',"
2388 			"'etag': '\"tbWC5XrSXxe1WOAx6MK9z4hHSU8/1v2mrzYSYG6onNLt2qTj13hkQZk\"',"
2389 			"'items': ["
2390 				"{"
2391 					"'kind': 'youtube#videoCategory',"
2392 					"'etag': '\"tbWC5XrSXxe1WOAx6MK9z4hHSU8/Xy1mB4_yLrHy_BmKmPBggty2mZQ\"',"
2393 					"'id': '1',"
2394 					"'snippet': {"
2395 						"'channelId': 'UCBR8-60-B28hp2BmDPdntcQ',"
2396 						"'title': 'Film & Animation',"
2397 						"'assignable': true"
2398 					"}"
2399 				"},"
2400 				"{"
2401 					"'kind': 'youtube#videoCategory',"
2402 					"'etag': '\"tbWC5XrSXxe1WOAx6MK9z4hHSU8/UZ1oLIIz2dxIhO45ZTFR3a3NyTA\"',"
2403 					"'id': '2',"
2404 					"'snippet': {"
2405 						"'channelId': 'UCBR8-60-B28hp2BmDPdntcQ',"
2406 						"'title': 'Autos & Vehicles',"
2407 						"'assignable': true"
2408 					"}"
2409 				"}"
2410 			"]"
2411 		"}", -1, &error));
2412 	g_assert_no_error (error);
2413 	g_assert (GDATA_IS_APP_CATEGORIES (categories));
2414 	g_clear_error (&error);
2415 
2416 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (categories));
2417 	g_assert_cmpstr (content_type, ==, "application/json");
2418 
2419 	/* Check the properties */
2420 	g_assert (gdata_app_categories_is_fixed (categories) == FALSE);
2421 
2422 	/* Check them a different way too */
2423 	g_object_get (G_OBJECT (categories), "is-fixed", &fixed, NULL);
2424 	g_assert (fixed == FALSE);
2425 
2426 	/* Check the categories and scheme inheritance */
2427 	_categories = gdata_app_categories_get_categories (categories);
2428 	g_assert_cmpint (g_list_length (_categories), ==, 2);
2429 
2430 	g_assert (GDATA_IS_CATEGORY (_categories->data));
2431 	g_assert_cmpstr (gdata_category_get_scheme (GDATA_CATEGORY (_categories->data)), ==, NULL);
2432 	g_assert_cmpstr (gdata_category_get_label (GDATA_CATEGORY (_categories->data)), ==, "Film & Animation");
2433 
2434 	g_assert (GDATA_IS_CATEGORY (_categories->next->data));
2435 	g_assert_cmpstr (gdata_category_get_scheme (GDATA_CATEGORY (_categories->next->data)), ==, NULL);
2436 	g_assert_cmpstr (gdata_category_get_label (GDATA_CATEGORY (_categories->next->data)), ==, "Autos & Vehicles");
2437 
2438 	g_object_unref (categories);
2439 
2440 	/* Now parse one with less information available */
2441 	categories = GDATA_APP_CATEGORIES (gdata_parsable_new_from_json (GDATA_TYPE_APP_CATEGORIES,
2442 		"{"
2443 			"'kind': 'youtube#videoCategoryListResponse',"
2444 			"'items': []"
2445 		"}", -1, &error));
2446 	g_assert_no_error (error);
2447 	g_assert (GDATA_IS_APP_CATEGORIES (categories));
2448 	g_clear_error (&error);
2449 
2450 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (categories));
2451 	g_assert_cmpstr (content_type, ==, "application/json");
2452 
2453 	/* Check the properties */
2454 	g_assert (gdata_app_categories_is_fixed (categories) == FALSE);
2455 	g_object_unref (categories);
2456 }
2457 
2458 static void
test_gd_email_address(void)2459 test_gd_email_address (void)
2460 {
2461 	GDataGDEmailAddress *email, *email2;
2462 	GError *error = NULL;
2463 	const gchar *content_type;
2464 
2465 	email = GDATA_GD_EMAIL_ADDRESS (gdata_parsable_new_from_xml (GDATA_TYPE_GD_EMAIL_ADDRESS,
2466 		"<gd:email xmlns:gd='http://schemas.google.com/g/2005' label='Personal &amp; Private' rel='http://schemas.google.com/g/2005#home' "
2467 			"address='fubar@gmail.com' primary='true' displayName='&lt;John Smith&gt;'/>", -1, &error));
2468 	g_assert_no_error (error);
2469 	g_assert (GDATA_IS_GD_EMAIL_ADDRESS (email));
2470 	g_clear_error (&error);
2471 
2472 	/* Check the properties */
2473 	g_assert_cmpstr (gdata_gd_email_address_get_address (email), ==, "fubar@gmail.com");
2474 	g_assert_cmpstr (gdata_gd_email_address_get_relation_type (email), ==, GDATA_GD_EMAIL_ADDRESS_HOME);
2475 	g_assert_cmpstr (gdata_gd_email_address_get_label (email), ==, "Personal & Private");
2476 	g_assert_cmpstr (gdata_gd_email_address_get_display_name (email), ==, "<John Smith>");
2477 	g_assert (gdata_gd_email_address_is_primary (email) == TRUE);
2478 
2479 	/* Compare it against another identical address */
2480 	email2 = gdata_gd_email_address_new ("fubar@gmail.com", GDATA_GD_EMAIL_ADDRESS_HOME, "Personal & Private", TRUE);
2481 	gdata_gd_email_address_set_display_name (email2, "<John Smith>");
2482 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (email), GDATA_COMPARABLE (email2)), ==, 0);
2483 
2484 	/* …and a different one */
2485 	gdata_gd_email_address_set_address (email2, "test@example.com");
2486 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (email), GDATA_COMPARABLE (email2)), !=, 0);
2487 	g_object_unref (email2);
2488 
2489 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (email));
2490 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
2491 
2492 	/* Check the outputted XML is the same */
2493 	gdata_test_assert_xml (email,
2494 			 "<?xml version='1.0' encoding='UTF-8'?>"
2495 			 "<gd:email xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' address='fubar@gmail.com' "
2496 				"rel='http://schemas.google.com/g/2005#home' label='Personal &amp; Private' displayName='&lt;John Smith&gt;' "
2497 				"primary='true'/>");
2498 	g_object_unref (email);
2499 
2500 	/* Now parse an address with less information available */
2501 	email = GDATA_GD_EMAIL_ADDRESS (gdata_parsable_new_from_xml (GDATA_TYPE_GD_EMAIL_ADDRESS,
2502 		"<gd:email xmlns:gd='http://schemas.google.com/g/2005' address='test@example.com'/>", -1, &error));
2503 	g_assert_no_error (error);
2504 	g_assert (GDATA_IS_GD_EMAIL_ADDRESS (email));
2505 	g_clear_error (&error);
2506 
2507 	/* Check the properties */
2508 	g_assert_cmpstr (gdata_gd_email_address_get_address (email), ==, "test@example.com");
2509 	g_assert (gdata_gd_email_address_get_relation_type (email) == NULL);
2510 	g_assert (gdata_gd_email_address_get_label (email) == NULL);
2511 	g_assert (gdata_gd_email_address_get_display_name (email) == NULL);
2512 	g_assert (gdata_gd_email_address_is_primary (email) == FALSE);
2513 
2514 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (email));
2515 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
2516 
2517 	/* Check the outputted XML contains the unknown XML */
2518 	gdata_test_assert_xml (email,
2519 			 "<?xml version='1.0' encoding='UTF-8'?>"
2520 			 "<gd:email xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' address='test@example.com' "
2521 				"primary='false'/>");
2522 	g_object_unref (email);
2523 }
2524 
2525 static void
test_gd_email_address_escaping(void)2526 test_gd_email_address_escaping (void)
2527 {
2528 	GDataGDEmailAddress *email;
2529 
2530 	g_test_bug ("630350");
2531 
2532 	email = gdata_gd_email_address_new ("Fubar <fubar@gmail.com>", GDATA_GD_EMAIL_ADDRESS_HOME "?foo&bar", "Personal & Private", TRUE);
2533 	gdata_gd_email_address_set_display_name (email, "<John Smith>");
2534 
2535 	/* Check the outputted XML is escaped properly */
2536 	gdata_test_assert_xml (email,
2537 	                 "<?xml version='1.0' encoding='UTF-8'?>"
2538 	                 "<gd:email xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
2539 	                           "address='Fubar &lt;fubar@gmail.com&gt;' rel='http://schemas.google.com/g/2005#home?foo&amp;bar' "
2540 	                           "label='Personal &amp; Private' displayName='&lt;John Smith&gt;' primary='true'/>");
2541 	g_object_unref (email);
2542 }
2543 
2544 static void
test_gd_email_address_comparison(void)2545 test_gd_email_address_comparison (void)
2546 {
2547 	GDataGDEmailAddress *email1, *email2;
2548 
2549 	/* Should only compare equal if addresses are equal. */
2550 	email1 = gdata_gd_email_address_new ("foo@example.com", NULL, NULL, TRUE);
2551 	email2 = gdata_gd_email_address_new ("foo@example.com", NULL, "label", FALSE);
2552 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (email1), GDATA_COMPARABLE (email2)), ==, 0);
2553 
2554 	gdata_gd_email_address_set_address (email1, "bar@example.com");
2555 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (email1), GDATA_COMPARABLE (email2)), !=, 0);
2556 
2557 	g_object_unref (email2);
2558 	g_object_unref (email1);
2559 }
2560 
2561 static void
test_gd_im_address(void)2562 test_gd_im_address (void)
2563 {
2564 	GDataGDIMAddress *im, *im2;
2565 	GError *error = NULL;
2566 	const gchar *content_type;
2567 
2568 	im = GDATA_GD_IM_ADDRESS (gdata_parsable_new_from_xml (GDATA_TYPE_GD_IM_ADDRESS,
2569 		"<gd:im xmlns:gd='http://schemas.google.com/g/2005' protocol='http://schemas.google.com/g/2005#MSN' address='foo@bar.msn.com' "
2570 			"rel='http://schemas.google.com/g/2005#home' primary='true'/>", -1, &error));
2571 	g_assert_no_error (error);
2572 	g_assert (GDATA_IS_GD_IM_ADDRESS (im));
2573 	g_clear_error (&error);
2574 
2575 	/* Check the properties */
2576 	g_assert_cmpstr (gdata_gd_im_address_get_address (im), ==, "foo@bar.msn.com");
2577 	g_assert_cmpstr (gdata_gd_im_address_get_protocol (im), ==, GDATA_GD_IM_PROTOCOL_LIVE_MESSENGER);
2578 	g_assert_cmpstr (gdata_gd_im_address_get_relation_type (im), ==, GDATA_GD_IM_ADDRESS_HOME);
2579 	g_assert (gdata_gd_im_address_get_label (im) == NULL);
2580 	g_assert (gdata_gd_im_address_is_primary (im) == TRUE);
2581 
2582 	/* Compare it against another identical address */
2583 	im2 = gdata_gd_im_address_new ("foo@bar.msn.com", GDATA_GD_IM_PROTOCOL_LIVE_MESSENGER, GDATA_GD_IM_ADDRESS_HOME, NULL, TRUE);
2584 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (im), GDATA_COMPARABLE (im2)), ==, 0);
2585 
2586 	/* …and a different one */
2587 	gdata_gd_im_address_set_protocol (im2, GDATA_GD_IM_PROTOCOL_GOOGLE_TALK);
2588 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (im), GDATA_COMPARABLE (im2)), !=, 0);
2589 	g_object_unref (im2);
2590 
2591 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (im));
2592 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
2593 
2594 	/* Check the outputted XML is the same */
2595 	gdata_test_assert_xml (im,
2596 			 "<?xml version='1.0' encoding='UTF-8'?>"
2597 			 "<gd:im xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
2598 				"address='foo@bar.msn.com' protocol='http://schemas.google.com/g/2005#MSN' "
2599 				"rel='http://schemas.google.com/g/2005#home' primary='true'/>");
2600 	g_object_unref (im);
2601 
2602 	/* Now parse an address with less information available */
2603 	im = GDATA_GD_IM_ADDRESS (gdata_parsable_new_from_xml (GDATA_TYPE_GD_IM_ADDRESS,
2604 		"<gd:im xmlns:gd='http://schemas.google.com/g/2005' label='Other &amp; Miscellaneous' address='foo@baz.example.com'/>", -1, &error));
2605 	g_assert_no_error (error);
2606 	g_assert (GDATA_IS_GD_IM_ADDRESS (im));
2607 	g_clear_error (&error);
2608 
2609 	/* Check the properties */
2610 	g_assert_cmpstr (gdata_gd_im_address_get_address (im), ==, "foo@baz.example.com");
2611 	g_assert (gdata_gd_im_address_get_protocol (im) == NULL);
2612 	g_assert (gdata_gd_im_address_get_relation_type (im) == NULL);
2613 	g_assert_cmpstr (gdata_gd_im_address_get_label (im), ==, "Other & Miscellaneous");
2614 	g_assert (gdata_gd_im_address_is_primary (im) == FALSE);
2615 
2616 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (im));
2617 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
2618 
2619 	/* Check the outputted XML contains the unknown XML */
2620 	gdata_test_assert_xml (im,
2621 			 "<?xml version='1.0' encoding='UTF-8'?>"
2622 			 "<gd:im xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' address='foo@baz.example.com' "
2623 				"label='Other &amp; Miscellaneous' primary='false'/>");
2624 	g_object_unref (im);
2625 }
2626 
2627 static void
test_gd_im_address_escaping(void)2628 test_gd_im_address_escaping (void)
2629 {
2630 	GDataGDIMAddress *im;
2631 
2632 	im = gdata_gd_im_address_new ("Fubar <fubar@gmail.com>", GDATA_GD_IM_PROTOCOL_GOOGLE_TALK "?foo&bar", GDATA_GD_IM_ADDRESS_HOME "?foo&bar",
2633 	                              "Personal & Private", TRUE);
2634 
2635 	/* Check the outputted XML is escaped properly */
2636 	gdata_test_assert_xml (im,
2637 	                 "<?xml version='1.0' encoding='UTF-8'?>"
2638 	                 "<gd:im xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
2639 	                        "address='Fubar &lt;fubar@gmail.com&gt;' protocol='http://schemas.google.com/g/2005#GOOGLE_TALK?foo&amp;bar' "
2640 	                        "rel='http://schemas.google.com/g/2005#home?foo&amp;bar' label='Personal &amp; Private' primary='true'/>");
2641 	g_object_unref (im);
2642 }
2643 
2644 static void
test_gd_im_address_comparison(void)2645 test_gd_im_address_comparison (void)
2646 {
2647 	GDataGDIMAddress *im_address1, *im_address2;
2648 
2649 	/* Should only compare equal if address and protocol are both equal. */
2650 	im_address1 = gdata_gd_im_address_new ("foo@example.com", GDATA_GD_IM_PROTOCOL_LIVE_MESSENGER, NULL, NULL, TRUE);
2651 	im_address2 = gdata_gd_im_address_new ("foo@example.com", GDATA_GD_IM_PROTOCOL_LIVE_MESSENGER, NULL, "label", FALSE);
2652 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (im_address1), GDATA_COMPARABLE (im_address2)), ==, 0);
2653 
2654 	/* Different addresses, same protocol. */
2655 	gdata_gd_im_address_set_address (im_address1, "bar@example.com");
2656 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (im_address1), GDATA_COMPARABLE (im_address2)), !=, 0);
2657 
2658 	/* Same address, different protocols. */
2659 	gdata_gd_im_address_set_address (im_address1, "foo@example.com");
2660 	gdata_gd_im_address_set_protocol (im_address1, GDATA_GD_IM_PROTOCOL_JABBER);
2661 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (im_address1), GDATA_COMPARABLE (im_address2)), !=, 0);
2662 
2663 	g_object_unref (im_address2);
2664 	g_object_unref (im_address1);
2665 }
2666 
2667 static void
test_gd_name(void)2668 test_gd_name (void)
2669 {
2670 	GDataGDName *name, *name2;
2671 	GError *error = NULL;
2672 	const gchar *content_type;
2673 
2674 	name = GDATA_GD_NAME (gdata_parsable_new_from_xml (GDATA_TYPE_GD_NAME,
2675 		"<gd:name xmlns:gd='http://schemas.google.com/g/2005'>"
2676 			"<gd:givenName>Brian</gd:givenName>"
2677 			"<gd:additionalName>Charles</gd:additionalName>"
2678 			"<gd:familyName>Blessed</gd:familyName>"
2679 			"<gd:namePrefix>Mr</gd:namePrefix>"
2680 			"<gd:nameSuffix>ABC</gd:nameSuffix>"
2681 			"<gd:fullName>Mr Brian Charles Blessed, ABC</gd:fullName>"
2682 		"</gd:name>", -1, &error));
2683 	g_assert_no_error (error);
2684 	g_assert (GDATA_IS_GD_NAME (name));
2685 	g_clear_error (&error);
2686 
2687 	/* Check the properties */
2688 	g_assert_cmpstr (gdata_gd_name_get_given_name (name), ==, "Brian");
2689 	g_assert_cmpstr (gdata_gd_name_get_additional_name (name), ==, "Charles");
2690 	g_assert_cmpstr (gdata_gd_name_get_family_name (name), ==, "Blessed");
2691 	g_assert_cmpstr (gdata_gd_name_get_prefix (name), ==, "Mr");
2692 	g_assert_cmpstr (gdata_gd_name_get_suffix (name), ==, "ABC");
2693 	g_assert_cmpstr (gdata_gd_name_get_full_name (name), ==, "Mr Brian Charles Blessed, ABC");
2694 
2695 	/* Compare it against another identical name */
2696 	name2 = gdata_gd_name_new ("Brian", "Blessed");
2697 	gdata_gd_name_set_additional_name (name2, "Charles");
2698 	gdata_gd_name_set_prefix (name2, "Mr");
2699 	gdata_gd_name_set_suffix (name2, "ABC");
2700 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (name), GDATA_COMPARABLE (name2)), ==, 0);
2701 
2702 	/* …and a different one */
2703 	gdata_gd_name_set_prefix (name2, "Mrs");
2704 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (name), GDATA_COMPARABLE (name2)), !=, 0);
2705 	g_object_unref (name2);
2706 
2707 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (name));
2708 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
2709 
2710 	/* Check the outputted XML is the same */
2711 	gdata_test_assert_xml (name,
2712 			 "<?xml version='1.0' encoding='UTF-8'?>"
2713 			 "<gd:name xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005'>"
2714 				"<gd:givenName>Brian</gd:givenName>"
2715 				"<gd:additionalName>Charles</gd:additionalName>"
2716 				"<gd:familyName>Blessed</gd:familyName>"
2717 				"<gd:namePrefix>Mr</gd:namePrefix>"
2718 				"<gd:nameSuffix>ABC</gd:nameSuffix>"
2719 				"<gd:fullName>Mr Brian Charles Blessed, ABC</gd:fullName>"
2720 			 "</gd:name>");
2721 	g_object_unref (name);
2722 
2723 	/* Now parse an address with less information available */
2724 	name = GDATA_GD_NAME (gdata_parsable_new_from_xml (GDATA_TYPE_GD_NAME,
2725 		"<gd:name xmlns:gd='http://schemas.google.com/g/2005'><gd:givenName>Bob</gd:givenName></gd:name>", -1, &error));
2726 	g_assert_no_error (error);
2727 	g_assert (GDATA_IS_GD_NAME (name));
2728 	g_clear_error (&error);
2729 
2730 	/* Check the properties */
2731 	g_assert_cmpstr (gdata_gd_name_get_given_name (name), ==, "Bob");
2732 	g_assert (gdata_gd_name_get_additional_name (name) == NULL);
2733 	g_assert (gdata_gd_name_get_family_name (name) == NULL);
2734 	g_assert (gdata_gd_name_get_prefix (name) == NULL);
2735 	g_assert (gdata_gd_name_get_suffix (name) == NULL);
2736 	g_assert (gdata_gd_name_get_full_name (name) == NULL);
2737 
2738 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (name));
2739 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
2740 
2741 	/* Check the outputted XML is still correct */
2742 	gdata_test_assert_xml (name,
2743 			 "<?xml version='1.0' encoding='UTF-8'?>"
2744 			 "<gd:name xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005'>"
2745 				"<gd:givenName>Bob</gd:givenName>"
2746 			 "</gd:name>");
2747 	g_object_unref (name);
2748 }
2749 
2750 static void
test_gd_name_empty_strings(void)2751 test_gd_name_empty_strings (void)
2752 {
2753 	GDataGDName *name;
2754 	GError *error = NULL;
2755 
2756 	g_test_bug ("662290");
2757 
2758 	/* Test that empty full names get treated as NULL correctly. */
2759 	name = GDATA_GD_NAME (gdata_parsable_new_from_xml (GDATA_TYPE_GD_NAME,
2760 		"<gd:name xmlns:gd='http://schemas.google.com/g/2005'>"
2761 			"<gd:fullName></gd:fullName>"
2762 		"</gd:name>", -1, &error));
2763 	g_assert_no_error (error);
2764 	g_assert (GDATA_IS_GD_NAME (name));
2765 	g_clear_error (&error);
2766 
2767 	/* Check the properties */
2768 	g_assert_cmpstr (gdata_gd_name_get_given_name (name), ==, NULL);
2769 	g_assert_cmpstr (gdata_gd_name_get_additional_name (name), ==, NULL);
2770 	g_assert_cmpstr (gdata_gd_name_get_family_name (name), ==, NULL);
2771 	g_assert_cmpstr (gdata_gd_name_get_prefix (name), ==, NULL);
2772 	g_assert_cmpstr (gdata_gd_name_get_suffix (name), ==, NULL);
2773 	g_assert_cmpstr (gdata_gd_name_get_full_name (name), ==, NULL);
2774 
2775 	g_object_unref (name);
2776 
2777 	/* Build a name with an empty string full name and check the serialisation */
2778 	name = gdata_gd_name_new ("Georgey", "Porgey");
2779 	gdata_gd_name_set_full_name (name, "");
2780 
2781 	g_assert_cmpstr (gdata_gd_name_get_full_name (name), ==, NULL);
2782 
2783 	/* Check the outputted XML is the same */
2784 	gdata_test_assert_xml (name,
2785 		"<?xml version='1.0' encoding='UTF-8'?>"
2786 		"<gd:name xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005'>"
2787 			"<gd:givenName>Georgey</gd:givenName>"
2788 			"<gd:familyName>Porgey</gd:familyName>"
2789 		"</gd:name>");
2790 
2791 	g_object_unref (name);
2792 }
2793 
2794 static void
test_gd_name_comparison(void)2795 test_gd_name_comparison (void)
2796 {
2797 	GDataGDName *name1, *name2;
2798 
2799 	/* Names are only equal if the given, additional and family names are all equal, and the prefixes are equal too. */
2800 	name1 = gdata_gd_name_new ("Given", "Family");
2801 	gdata_gd_name_set_additional_name (name1, "Additional");
2802 	gdata_gd_name_set_prefix (name1, "Mrs");
2803 	name2 = gdata_gd_name_new ("Given", "Family");
2804 	gdata_gd_name_set_additional_name (name2, "Additional");
2805 	gdata_gd_name_set_prefix (name2, "Mrs");
2806 
2807 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (name1), GDATA_COMPARABLE (name2)), ==, 0);
2808 
2809 	/* Different given names. */
2810 	gdata_gd_name_set_given_name (name1, "Different");
2811 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (name1), GDATA_COMPARABLE (name2)), !=, 0);
2812 
2813 	/* Different additional names. */
2814 	gdata_gd_name_set_given_name (name1, "Given");
2815 	gdata_gd_name_set_additional_name (name1, "Different");
2816 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (name1), GDATA_COMPARABLE (name2)), !=, 0);
2817 
2818 	/* Different family names. */
2819 	gdata_gd_name_set_additional_name (name1, "Additional");
2820 	gdata_gd_name_set_family_name (name1, "Different");
2821 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (name1), GDATA_COMPARABLE (name2)), !=, 0);
2822 
2823 	/* Different prefixes. */
2824 	gdata_gd_name_set_family_name (name1, "Family");
2825 	gdata_gd_name_set_prefix (name1, "Mr");
2826 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (name1), GDATA_COMPARABLE (name2)), !=, 0);
2827 
2828 	g_object_unref (name2);
2829 	g_object_unref (name1);
2830 }
2831 
2832 static void
test_gd_organization(void)2833 test_gd_organization (void)
2834 {
2835 	GDataGDOrganization *org, *org2;
2836 	GDataGDWhere *location;
2837 	GError *error = NULL;
2838 	const gchar *content_type;
2839 
2840 	org = GDATA_GD_ORGANIZATION (gdata_parsable_new_from_xml (GDATA_TYPE_GD_ORGANIZATION,
2841 		"<gd:organization xmlns:gd='http://schemas.google.com/g/2005' rel='http://schemas.google.com/g/2005#work' label='Work &amp; Occupation' "
2842 			"primary='true'>"
2843 			"<gd:orgName>Google, Inc.</gd:orgName>"
2844 			"<gd:orgTitle>&lt;Angle Bracketeer&gt;</gd:orgTitle>"
2845 			"<gd:orgDepartment>Finance</gd:orgDepartment>"
2846 			"<gd:orgJobDescription>Doing stuff.</gd:orgJobDescription>"
2847 			"<gd:orgSymbol>FOO</gd:orgSymbol>"
2848 			"<gd:where valueString='Test location'/>"
2849 		"</gd:organization>", -1, &error));
2850 	g_assert_no_error (error);
2851 	g_assert (GDATA_IS_GD_ORGANIZATION (org));
2852 	g_clear_error (&error);
2853 
2854 	/* Check the properties */
2855 	g_assert_cmpstr (gdata_gd_organization_get_name (org), ==, "Google, Inc.");
2856 	g_assert_cmpstr (gdata_gd_organization_get_title (org), ==, "<Angle Bracketeer>");
2857 	g_assert_cmpstr (gdata_gd_organization_get_relation_type (org), ==, GDATA_GD_ORGANIZATION_WORK);
2858 	g_assert_cmpstr (gdata_gd_organization_get_label (org), ==, "Work & Occupation");
2859 	g_assert_cmpstr (gdata_gd_organization_get_department (org), ==, "Finance");
2860 	g_assert_cmpstr (gdata_gd_organization_get_job_description (org), ==, "Doing stuff.");
2861 	g_assert_cmpstr (gdata_gd_organization_get_symbol (org), ==, "FOO");
2862 	location = gdata_gd_organization_get_location (org);
2863 	g_assert (GDATA_IS_GD_WHERE (location));
2864 	g_assert (gdata_gd_organization_is_primary (org) == TRUE);
2865 
2866 	/* Compare it against another identical organization */
2867 	org2 = gdata_gd_organization_new ("Google, Inc.", "<Angle Bracketeer>", GDATA_GD_ORGANIZATION_WORK, "Work & Occupation", TRUE);
2868 	gdata_gd_organization_set_department (org2, "Finance");
2869 	gdata_gd_organization_set_location (org2, location);
2870 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (org), GDATA_COMPARABLE (org2)), ==, 0);
2871 
2872 	/* …and a different one */
2873 	gdata_gd_organization_set_title (org2, "Demoted!");
2874 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (org), GDATA_COMPARABLE (org2)), !=, 0);
2875 	g_object_unref (org2);
2876 
2877 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (org));
2878 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
2879 
2880 	/* Check the outputted XML is the same */
2881 	gdata_test_assert_xml (org,
2882 			 "<?xml version='1.0' encoding='UTF-8'?>"
2883 			 "<gd:organization xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
2884 				"rel='http://schemas.google.com/g/2005#work' label='Work &amp; Occupation' primary='true'>"
2885 				"<gd:orgName>Google, Inc.</gd:orgName>"
2886 				"<gd:orgTitle>&lt;Angle Bracketeer&gt;</gd:orgTitle>"
2887 				"<gd:orgDepartment>Finance</gd:orgDepartment>"
2888 				"<gd:orgJobDescription>Doing stuff.</gd:orgJobDescription>"
2889 				"<gd:orgSymbol>FOO</gd:orgSymbol>"
2890 				"<gd:where valueString='Test location'/>"
2891 			 "</gd:organization>");
2892 	g_object_unref (org);
2893 
2894 	/* Now parse an organization with less information available */
2895 	org = GDATA_GD_ORGANIZATION (gdata_parsable_new_from_xml (GDATA_TYPE_GD_ORGANIZATION,
2896 		"<gd:organization xmlns:gd='http://schemas.google.com/g/2005'/>", -1, &error));
2897 	g_assert_no_error (error);
2898 	g_assert (GDATA_IS_GD_ORGANIZATION (org));
2899 	g_clear_error (&error);
2900 
2901 	/* Check the properties */
2902 	g_assert (gdata_gd_organization_get_name (org) == NULL);
2903 	g_assert (gdata_gd_organization_get_title (org) == NULL);
2904 	g_assert (gdata_gd_organization_get_relation_type (org) == NULL);
2905 	g_assert (gdata_gd_organization_get_label (org) == NULL);
2906 	g_assert (gdata_gd_organization_is_primary (org) == FALSE);
2907 	g_assert (gdata_gd_organization_get_department (org) == NULL);
2908 	g_assert (gdata_gd_organization_get_job_description (org) == NULL);
2909 	g_assert (gdata_gd_organization_get_symbol (org) == NULL);
2910 	g_assert (gdata_gd_organization_get_location (org) == NULL);
2911 
2912 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (org));
2913 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
2914 
2915 	/* Check the outputted XML contains the unknown XML */
2916 	gdata_test_assert_xml (org,
2917 			 "<?xml version='1.0' encoding='UTF-8'?>"
2918 			 "<gd:organization xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' primary='false'/>");
2919 	g_object_unref (org);
2920 }
2921 
2922 static void
test_gd_organization_escaping(void)2923 test_gd_organization_escaping (void)
2924 {
2925 	GDataGDOrganization *org;
2926 
2927 	org = gdata_gd_organization_new ("Steptoe & Son", "Title & Stuff", GDATA_GD_ORGANIZATION_WORK "?foo&bar", "Personal & Private", TRUE);
2928 	gdata_gd_organization_set_department (org, "Department & Stuff");
2929 	gdata_gd_organization_set_job_description (org, "Escaping <brackets>.");
2930 	gdata_gd_organization_set_symbol (org, "<&>");
2931 
2932 	/* Check the outputted XML is escaped properly */
2933 	gdata_test_assert_xml (org,
2934 	                 "<?xml version='1.0' encoding='UTF-8'?>"
2935 	                 "<gd:organization xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
2936 	                                  "rel='http://schemas.google.com/g/2005#work?foo&amp;bar' label='Personal &amp; Private' primary='true'>"
2937 	                         "<gd:orgName>Steptoe &amp; Son</gd:orgName>"
2938 	                         "<gd:orgTitle>Title &amp; Stuff</gd:orgTitle>"
2939 	                         "<gd:orgDepartment>Department &amp; Stuff</gd:orgDepartment>"
2940 	                         "<gd:orgJobDescription>Escaping &lt;brackets&gt;.</gd:orgJobDescription>"
2941 	                         "<gd:orgSymbol>&lt;&amp;&gt;</gd:orgSymbol>"
2942 	                 "</gd:organization>");
2943 	g_object_unref (org);
2944 }
2945 
2946 static void
test_gd_organization_comparison(void)2947 test_gd_organization_comparison (void)
2948 {
2949 	GDataGDOrganization *org1, *org2;
2950 
2951 	/* Organisation positions are equal if the name, title and department are all equal. */
2952 	org1 = gdata_gd_organization_new ("Name", "Title", NULL, NULL, TRUE);
2953 	gdata_gd_organization_set_department (org1, "Department");
2954 	org2 = gdata_gd_organization_new ("Name", "Title", NULL, "label", FALSE);
2955 	gdata_gd_organization_set_department (org2, "Department");
2956 
2957 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (org1), GDATA_COMPARABLE (org2)), ==, 0);
2958 
2959 	/* Different name. */
2960 	gdata_gd_organization_set_name (org1, "Different");
2961 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (org1), GDATA_COMPARABLE (org2)), !=, 0);
2962 
2963 	/* Different title. */
2964 	gdata_gd_organization_set_name (org1, "Name");
2965 	gdata_gd_organization_set_title (org1, "Different");
2966 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (org1), GDATA_COMPARABLE (org2)), !=, 0);
2967 
2968 	/* Different department. */
2969 	gdata_gd_organization_set_title (org1, "Title");
2970 	gdata_gd_organization_set_department (org1, "Different");
2971 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (org1), GDATA_COMPARABLE (org2)), !=, 0);
2972 
2973 	g_object_unref (org2);
2974 	g_object_unref (org1);
2975 }
2976 
2977 static void
test_gd_phone_number(void)2978 test_gd_phone_number (void)
2979 {
2980 	GDataGDPhoneNumber *phone, *phone2;
2981 	GError *error = NULL;
2982 	const gchar *content_type;
2983 
2984 	phone = GDATA_GD_PHONE_NUMBER (gdata_parsable_new_from_xml (GDATA_TYPE_GD_PHONE_NUMBER,
2985 		"<gd:phoneNumber xmlns:gd='http://schemas.google.com/g/2005' rel='http://schemas.google.com/g/2005#mobile' "
2986 			"label='Personal &amp; business calls only' uri='tel:+12065551212'>+1 206 555 1212</gd:phoneNumber>", -1, &error));
2987 	g_assert_no_error (error);
2988 	g_assert (GDATA_IS_GD_PHONE_NUMBER (phone));
2989 	g_clear_error (&error);
2990 
2991 	/* Check the properties */
2992 	g_assert_cmpstr (gdata_gd_phone_number_get_number (phone), ==, "+1 206 555 1212");
2993 	g_assert_cmpstr (gdata_gd_phone_number_get_uri (phone), ==, "tel:+12065551212");
2994 	g_assert_cmpstr (gdata_gd_phone_number_get_relation_type (phone), ==, GDATA_GD_PHONE_NUMBER_MOBILE);
2995 	g_assert_cmpstr (gdata_gd_phone_number_get_label (phone), ==, "Personal & business calls only");
2996 	g_assert (gdata_gd_phone_number_is_primary (phone) == FALSE);
2997 
2998 	/* Compare it against another identical number */
2999 	phone2 = gdata_gd_phone_number_new ("+1 206 555 1212", GDATA_GD_PHONE_NUMBER_MOBILE, "Personal & business calls only",
3000 					    "tel:+12065551212", FALSE);
3001 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (phone), GDATA_COMPARABLE (phone2)), ==, 0);
3002 
3003 	/* …and a different one */
3004 	gdata_gd_phone_number_set_number (phone2, "+1 206 555 1212 666");
3005 	gdata_gd_phone_number_set_uri (phone2, NULL);
3006 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (phone), GDATA_COMPARABLE (phone2)), !=, 0);
3007 	g_object_unref (phone2);
3008 
3009 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (phone));
3010 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3011 
3012 	/* Check the outputted XML is the same */
3013 	gdata_test_assert_xml (phone,
3014 			 "<?xml version='1.0' encoding='UTF-8'?>"
3015 			 "<gd:phoneNumber xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
3016 				"uri='tel:+12065551212' rel='http://schemas.google.com/g/2005#mobile' label='Personal &amp; business calls only' "
3017 				"primary='false'>+1 206 555 1212</gd:phoneNumber>");
3018 
3019 	/* Check we trim whitespace properly, and respect Unicode characters */
3020 	gdata_gd_phone_number_set_number (phone, "  	 0123456 (789) ëxt 300  ");
3021 	g_assert_cmpstr (gdata_gd_phone_number_get_number (phone), ==, "0123456 (789) ëxt 300");
3022 	g_object_unref (phone);
3023 
3024 	/* Now parse a phone number with less information available, but some extraneous whitespace */
3025 	phone = GDATA_GD_PHONE_NUMBER (gdata_parsable_new_from_xml (GDATA_TYPE_GD_PHONE_NUMBER,
3026 		"<gd:phoneNumber xmlns:gd='http://schemas.google.com/g/2005'>  (425) 555-8080 ext. 72585  \n </gd:phoneNumber>", -1, &error));
3027 	g_assert_no_error (error);
3028 	g_assert (GDATA_IS_GD_PHONE_NUMBER (phone));
3029 	g_clear_error (&error);
3030 
3031 	/* Check the properties */
3032 	g_assert_cmpstr (gdata_gd_phone_number_get_number (phone), ==, "(425) 555-8080 ext. 72585");
3033 	g_assert (gdata_gd_phone_number_get_uri (phone) == NULL);
3034 	g_assert (gdata_gd_phone_number_get_relation_type (phone) == NULL);
3035 	g_assert (gdata_gd_phone_number_get_label (phone) == NULL);
3036 	g_assert (gdata_gd_phone_number_is_primary (phone) == FALSE);
3037 
3038 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (phone));
3039 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3040 
3041 	/* Check the outputted XML contains the unknown XML */
3042 	gdata_test_assert_xml (phone,
3043 			 "<?xml version='1.0' encoding='UTF-8'?>"
3044 			 "<gd:phoneNumber xmlns='http://www.w3.org/2005/Atom' "
3045 				"xmlns:gd='http://schemas.google.com/g/2005' primary='false'>(425) 555-8080 ext. 72585</gd:phoneNumber>");
3046 	g_object_unref (phone);
3047 }
3048 
3049 static void
test_gd_phone_number_escaping(void)3050 test_gd_phone_number_escaping (void)
3051 {
3052 	GDataGDPhoneNumber *phone;
3053 
3054 	phone = gdata_gd_phone_number_new ("0123456789 <54>", GDATA_GD_PHONE_NUMBER_WORK_MOBILE "?foo&bar", "Personal & Private",
3055 	                                   "tel:+012345678954?foo&bar", TRUE);
3056 
3057 	/* Check the outputted XML is escaped properly */
3058 	gdata_test_assert_xml (phone,
3059 	                 "<?xml version='1.0' encoding='UTF-8'?>"
3060 	                 "<gd:phoneNumber xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
3061 	                                 "uri='tel:+012345678954?foo&amp;bar' rel='http://schemas.google.com/g/2005#work_mobile?foo&amp;bar' "
3062 	                                 "label='Personal &amp; Private' primary='true'>0123456789 &lt;54&gt;</gd:phoneNumber>");
3063 	g_object_unref (phone);
3064 }
3065 
3066 static void
test_gd_phone_number_comparison(void)3067 test_gd_phone_number_comparison (void)
3068 {
3069 	GDataGDPhoneNumber *phone1, *phone2;
3070 
3071 	/* Phone numbers are equal if the number or the URI matches (NULL URIs cannot match). */
3072 	phone1 = gdata_gd_phone_number_new ("123", NULL, NULL, "phone://123", TRUE);
3073 	phone2 = gdata_gd_phone_number_new ("123", NULL, "label", "phone://123", FALSE);
3074 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (phone1), GDATA_COMPARABLE (phone2)), ==, 0);
3075 
3076 	/* Same numbers, different URIs. */
3077 	gdata_gd_phone_number_set_uri (phone1, "phone://+44123");
3078 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (phone1), GDATA_COMPARABLE (phone2)), ==, 0);
3079 
3080 	/* Different numbers, same URIs. */
3081 	gdata_gd_phone_number_set_uri (phone1, "phone://123");
3082 	gdata_gd_phone_number_set_number (phone1, "+44123");
3083 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (phone1), GDATA_COMPARABLE (phone2)), ==, 0);
3084 
3085 	/* Different numbers and URIs. */
3086 	gdata_gd_phone_number_set_number (phone1, "456");
3087 	gdata_gd_phone_number_set_uri (phone1, "phone://456");
3088 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (phone1), GDATA_COMPARABLE (phone2)), !=, 0);
3089 
3090 	/* Different numbers, NULL URIs. */
3091 	gdata_gd_phone_number_set_uri (phone1, NULL);
3092 	gdata_gd_phone_number_set_uri (phone2, NULL);
3093 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (phone1), GDATA_COMPARABLE (phone2)), !=, 0);
3094 
3095 	/* Same numbers, NULL URIs. */
3096 	gdata_gd_phone_number_set_number (phone1, "123");
3097 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (phone1), GDATA_COMPARABLE (phone2)), ==, 0);
3098 
3099 	g_object_unref (phone2);
3100 	g_object_unref (phone1);
3101 }
3102 
3103 static void
test_gd_postal_address(void)3104 test_gd_postal_address (void)
3105 {
3106 	GDataGDPostalAddress *postal, *postal2;
3107 	GError *error = NULL;
3108 	const gchar *content_type;
3109 
3110 	postal = GDATA_GD_POSTAL_ADDRESS (gdata_parsable_new_from_xml (GDATA_TYPE_GD_POSTAL_ADDRESS,
3111 		"<gd:structuredPostalAddress xmlns:gd='http://schemas.google.com/g/2005' label='Home &amp; Safe House' "
3112 			"rel='http://schemas.google.com/g/2005#home' primary='true'>"
3113 			"<gd:street>500 West 45th Street</gd:street>"
3114 			"<gd:city>New York</gd:city>"
3115 			"<gd:postcode>NY 10036</gd:postcode>"
3116 			"<gd:country code='US'>United States</gd:country>"
3117 		"</gd:structuredPostalAddress>", -1, &error));
3118 	g_assert_no_error (error);
3119 	g_assert (GDATA_IS_GD_POSTAL_ADDRESS (postal));
3120 	g_clear_error (&error);
3121 
3122 	/* Check the properties */
3123 	g_assert_cmpstr (gdata_gd_postal_address_get_street (postal), ==, "500 West 45th Street");
3124 	g_assert_cmpstr (gdata_gd_postal_address_get_city (postal), ==, "New York");
3125 	g_assert_cmpstr (gdata_gd_postal_address_get_postcode (postal), ==, "NY 10036");
3126 	g_assert_cmpstr (gdata_gd_postal_address_get_relation_type (postal), ==, GDATA_GD_POSTAL_ADDRESS_HOME);
3127 	g_assert_cmpstr (gdata_gd_postal_address_get_label (postal), ==, "Home & Safe House");
3128 	g_assert_cmpstr (gdata_gd_postal_address_get_country (postal), ==, "United States");
3129 	g_assert_cmpstr (gdata_gd_postal_address_get_country_code (postal), ==, "US");
3130 	g_assert (gdata_gd_postal_address_is_primary (postal) == TRUE);
3131 
3132 	/* Compare it against another identical address */
3133 	postal2 = gdata_gd_postal_address_new (GDATA_GD_POSTAL_ADDRESS_HOME, "Home & Safe House", TRUE);
3134 	gdata_gd_postal_address_set_street (postal2, "500 West 45th Street");
3135 	gdata_gd_postal_address_set_city (postal2, "New York");
3136 	gdata_gd_postal_address_set_postcode (postal2, "NY 10036");
3137 	gdata_gd_postal_address_set_country (postal2, "United States", "US");
3138 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (postal), GDATA_COMPARABLE (postal2)), ==, 0);
3139 
3140 	/* …and a different one */
3141 	gdata_gd_postal_address_set_city (postal2, "Atlas Mountains");
3142 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (postal), GDATA_COMPARABLE (postal2)), !=, 0);
3143 	g_object_unref (postal2);
3144 
3145 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (postal));
3146 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3147 
3148 	/* Check the outputted XML is the same */
3149 	gdata_test_assert_xml (postal,
3150 			 "<?xml version='1.0' encoding='UTF-8'?>"
3151 			 "<gd:structuredPostalAddress xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
3152 				"rel='http://schemas.google.com/g/2005#home' label='Home &amp; Safe House' primary='true'>"
3153 				"<gd:street>500 West 45th Street</gd:street>"
3154 				"<gd:city>New York</gd:city>"
3155 				"<gd:postcode>NY 10036</gd:postcode>"
3156 				"<gd:country code='US'>United States</gd:country>"
3157 			 "</gd:structuredPostalAddress>");
3158 
3159 	/* Check we trim whitespace properly, and respect Unicode characters */
3160 	gdata_gd_postal_address_set_address (postal, "  	 Schöne Grüße Straße\nGermany  ");
3161 	g_assert_cmpstr (gdata_gd_postal_address_get_address (postal), ==, "Schöne Grüße Straße\nGermany");
3162 	g_object_unref (postal);
3163 
3164 	/* Now parse an address with less information available */
3165 	postal = GDATA_GD_POSTAL_ADDRESS (gdata_parsable_new_from_xml (GDATA_TYPE_GD_POSTAL_ADDRESS,
3166 		"<gd:structuredPostalAddress xmlns:gd='http://schemas.google.com/g/2005'><gd:street>f</gd:street></gd:structuredPostalAddress>",
3167 		-1, &error));
3168 	g_assert_no_error (error);
3169 	g_assert (GDATA_IS_GD_POSTAL_ADDRESS (postal));
3170 	g_clear_error (&error);
3171 
3172 	/* Check the properties */
3173 	g_assert_cmpstr (gdata_gd_postal_address_get_street (postal), ==, "f");
3174 	g_assert (gdata_gd_postal_address_get_relation_type (postal) == NULL);
3175 	g_assert (gdata_gd_postal_address_get_label (postal) == NULL);
3176 	g_assert (gdata_gd_postal_address_is_primary (postal) == FALSE);
3177 
3178 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (postal));
3179 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3180 
3181 	/* Check the outputted XML contains the unknown XML */
3182 	gdata_test_assert_xml (postal,
3183 			 "<?xml version='1.0' encoding='UTF-8'?>"
3184 			 "<gd:structuredPostalAddress xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' primary='false'>"
3185 				 "<gd:street>f</gd:street></gd:structuredPostalAddress>");
3186 	g_object_unref (postal);
3187 }
3188 
3189 static void
test_gd_postal_address_escaping(void)3190 test_gd_postal_address_escaping (void)
3191 {
3192 	GDataGDPostalAddress *address;
3193 
3194 	address = gdata_gd_postal_address_new (GDATA_GD_POSTAL_ADDRESS_WORK "?foo&bar", "Personal & Private", TRUE);
3195 	gdata_gd_postal_address_set_address (address, "<address>");
3196 	gdata_gd_postal_address_set_mail_class (address, GDATA_GD_MAIL_CLASS_BOTH "?foo&bar");
3197 	gdata_gd_postal_address_set_usage (address, GDATA_GD_ADDRESS_USAGE_GENERAL "?foo&bar");
3198 	gdata_gd_postal_address_set_agent (address, "<agent>");
3199 	gdata_gd_postal_address_set_house_name (address, "House & House");
3200 	gdata_gd_postal_address_set_street (address, "Church & Main Street");
3201 	gdata_gd_postal_address_set_po_box (address, "<515>");
3202 	gdata_gd_postal_address_set_neighborhood (address, "<neighbourhood>");
3203 	gdata_gd_postal_address_set_city (address, "City <17>");
3204 	gdata_gd_postal_address_set_subregion (address, "Subregion <5>");
3205 	gdata_gd_postal_address_set_region (address, "<region>");
3206 	gdata_gd_postal_address_set_postcode (address, "Postcode & stuff");
3207 	gdata_gd_postal_address_set_country (address, "<foo>", "<bar>");
3208 
3209 	/* Check the outputted XML is escaped properly */
3210 	gdata_test_assert_xml (address,
3211 	                 "<?xml version='1.0' encoding='UTF-8'?>"
3212 	                 "<gd:structuredPostalAddress xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
3213 	                                             "rel='http://schemas.google.com/g/2005#work?foo&amp;bar' label='Personal &amp; Private' "
3214 	                                             "mailClass='http://schemas.google.com/g/2005#both?foo&amp;bar' "
3215 	                                             "usage='http://schemas.google.com/g/2005#general?foo&amp;bar' primary='true'>"
3216 	                         "<gd:agent>&lt;agent&gt;</gd:agent>"
3217 	                         "<gd:housename>House &amp; House</gd:housename>"
3218 	                         "<gd:street>Church &amp; Main Street</gd:street>"
3219 	                         "<gd:pobox>&lt;515&gt;</gd:pobox>"
3220 	                         "<gd:neighborhood>&lt;neighbourhood&gt;</gd:neighborhood>"
3221 	                         "<gd:city>City &lt;17&gt;</gd:city>"
3222 	                         "<gd:subregion>Subregion &lt;5&gt;</gd:subregion>"
3223 	                         "<gd:region>&lt;region&gt;</gd:region>"
3224 	                         "<gd:postcode>Postcode &amp; stuff</gd:postcode>"
3225 	                         "<gd:country code='&lt;bar&gt;'>&lt;foo&gt;</gd:country>"
3226 	                         "<gd:formattedAddress>&lt;address&gt;</gd:formattedAddress>"
3227 	                 "</gd:structuredPostalAddress>");
3228 	g_object_unref (address);
3229 }
3230 
3231 static void
test_gd_postal_address_comparison(void)3232 test_gd_postal_address_comparison (void)
3233 {
3234 	GDataGDPostalAddress *address1, *address2;
3235 
3236 	/* Postal addresses compare equal if the street, city, PO box and postcode are all equal. */
3237 	address1 = gdata_gd_postal_address_new (NULL, NULL, TRUE);
3238 	gdata_gd_postal_address_set_street (address1, "Street");
3239 	gdata_gd_postal_address_set_city (address1, "City");
3240 	gdata_gd_postal_address_set_po_box (address1, "PO box");
3241 	gdata_gd_postal_address_set_postcode (address1, "Postcode");
3242 	address2 = gdata_gd_postal_address_new (NULL, "label", FALSE);
3243 	gdata_gd_postal_address_set_street (address2, "Street");
3244 	gdata_gd_postal_address_set_city (address2, "City");
3245 	gdata_gd_postal_address_set_po_box (address2, "PO box");
3246 	gdata_gd_postal_address_set_postcode (address2, "Postcode");
3247 
3248 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (address1), GDATA_COMPARABLE (address2)), ==, 0);
3249 
3250 	/* Different streets. */
3251 	gdata_gd_postal_address_set_street (address1, "Different");
3252 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (address1), GDATA_COMPARABLE (address2)), !=, 0);
3253 
3254 	/* Different cities. */
3255 	gdata_gd_postal_address_set_street (address1, "Street");
3256 	gdata_gd_postal_address_set_city (address1, "Different");
3257 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (address1), GDATA_COMPARABLE (address2)), !=, 0);
3258 
3259 	/* Different PO box. */
3260 	gdata_gd_postal_address_set_city (address1, "City");
3261 	gdata_gd_postal_address_set_po_box (address1, "Different");
3262 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (address1), GDATA_COMPARABLE (address2)), !=, 0);
3263 
3264 	/* Different postcode. */
3265 	gdata_gd_postal_address_set_po_box (address1, "PO box");
3266 	gdata_gd_postal_address_set_postcode (address1, "Different");
3267 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (address1), GDATA_COMPARABLE (address2)), !=, 0);
3268 
3269 	g_object_unref (address2);
3270 	g_object_unref (address1);
3271 }
3272 
3273 static void
test_gd_reminder(void)3274 test_gd_reminder (void)
3275 {
3276 	GDataGDReminder *reminder, *reminder2;
3277 	gint64 _time;
3278 	GError *error = NULL;
3279 	const gchar *content_type;
3280 
3281 	reminder = GDATA_GD_REMINDER (gdata_parsable_new_from_xml (GDATA_TYPE_GD_REMINDER,
3282 		"<gd:reminder xmlns:gd='http://schemas.google.com/g/2005' days='15'/>", -1, &error));
3283 	g_assert_no_error (error);
3284 	g_assert (GDATA_IS_GD_REMINDER (reminder));
3285 	g_clear_error (&error);
3286 
3287 	/* Check the properties */
3288 	g_assert (gdata_gd_reminder_get_method (reminder) == NULL);
3289 	g_assert (gdata_gd_reminder_is_absolute_time (reminder) == FALSE);
3290 	g_assert_cmpint (gdata_gd_reminder_get_relative_time (reminder), ==, 15 * 24 * 60);
3291 
3292 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (reminder));
3293 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3294 
3295 	/* Check the outputted XML */
3296 	gdata_test_assert_xml (reminder,
3297 			 "<?xml version='1.0' encoding='UTF-8'?>"
3298 			 "<gd:reminder xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' minutes='21600'/>");
3299 	g_object_unref (reminder);
3300 
3301 	/* Try again with a different property */
3302 	reminder = GDATA_GD_REMINDER (gdata_parsable_new_from_xml (GDATA_TYPE_GD_REMINDER,
3303 		"<gd:reminder xmlns:gd='http://schemas.google.com/g/2005' hours='15'/>", -1, &error));
3304 	g_assert_no_error (error);
3305 	g_assert (GDATA_IS_GD_REMINDER (reminder));
3306 	g_clear_error (&error);
3307 
3308 	/* Check the properties */
3309 	g_assert (gdata_gd_reminder_get_method (reminder) == NULL);
3310 	g_assert (gdata_gd_reminder_is_absolute_time (reminder) == FALSE);
3311 	g_assert_cmpint (gdata_gd_reminder_get_relative_time (reminder), ==, 15 * 60);
3312 
3313 	/* Compare to another reminder */
3314 	reminder2 = gdata_gd_reminder_new (NULL, -1, 15 * 60);
3315 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (reminder), GDATA_COMPARABLE (reminder2)), ==, 0);
3316 	g_object_unref (reminder2);
3317 	g_object_unref (reminder);
3318 
3319 	/* …and another */
3320 	reminder = GDATA_GD_REMINDER (gdata_parsable_new_from_xml (GDATA_TYPE_GD_REMINDER,
3321 		"<gd:reminder xmlns:gd='http://schemas.google.com/g/2005' minutes='15'/>", -1, &error));
3322 	g_assert_no_error (error);
3323 	g_assert (GDATA_IS_GD_REMINDER (reminder));
3324 	g_clear_error (&error);
3325 
3326 	/* Check the properties */
3327 	g_assert (gdata_gd_reminder_get_method (reminder) == NULL);
3328 	g_assert (gdata_gd_reminder_is_absolute_time (reminder) == FALSE);
3329 	g_assert_cmpint (gdata_gd_reminder_get_relative_time (reminder), ==, 15);
3330 	g_object_unref (reminder);
3331 
3332 	/* Try again with an absolute time and a method */
3333 	reminder = GDATA_GD_REMINDER (gdata_parsable_new_from_xml (GDATA_TYPE_GD_REMINDER,
3334 		"<gd:reminder xmlns:gd='http://schemas.google.com/g/2005' method='alert' absoluteTime='2005-06-06T16:55:00-08:00'/>", -1, &error));
3335 	g_assert_no_error (error);
3336 	g_assert (GDATA_IS_GD_REMINDER (reminder));
3337 	g_clear_error (&error);
3338 
3339 	/* Check the properties */
3340 	g_assert_cmpstr (gdata_gd_reminder_get_method (reminder), ==, GDATA_GD_REMINDER_ALERT);
3341 	g_assert (gdata_gd_reminder_is_absolute_time (reminder) == TRUE);
3342 	_time = gdata_gd_reminder_get_absolute_time (reminder);
3343 	g_assert_cmpint (_time, ==, 1118105700);
3344 
3345 	/* Compare to another reminder */
3346 	reminder2 = gdata_gd_reminder_new (GDATA_GD_REMINDER_ALERT, _time, -1);
3347 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (reminder), GDATA_COMPARABLE (reminder2)), ==, 0);
3348 	g_object_unref (reminder2);
3349 
3350 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (reminder));
3351 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3352 
3353 	/* Check the outputted XML */
3354 	gdata_test_assert_xml (reminder,
3355 			 "<?xml version='1.0' encoding='UTF-8'?>"
3356 			 "<gd:reminder xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
3357 				"absoluteTime='2005-06-07T00:55:00Z' method='alert'/>");
3358 	g_object_unref (reminder);
3359 }
3360 
3361 static void
test_gd_reminder_escaping(void)3362 test_gd_reminder_escaping (void)
3363 {
3364 	GDataGDReminder *reminder;
3365 
3366 	reminder = gdata_gd_reminder_new (GDATA_GD_REMINDER_ALERT "?foo&bar", -1, 15);
3367 
3368 	/* Check the outputted XML is escaped properly */
3369 	gdata_test_assert_xml (reminder,
3370 	                 "<?xml version='1.0' encoding='UTF-8'?>"
3371 	                 "<gd:reminder xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
3372 	                              "minutes='15' method='alert?foo&amp;bar'/>");
3373 	g_object_unref (reminder);
3374 }
3375 
3376 static void
test_gd_reminder_comparison(void)3377 test_gd_reminder_comparison (void)
3378 {
3379 	GDataGDReminder *reminder1, *reminder2;
3380 
3381 #define ASSERT_COMPARISON(op) \
3382 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (reminder1), GDATA_COMPARABLE (reminder2)), op, 0)
3383 
3384 	/* Check for equality. */
3385 	reminder1 = gdata_gd_reminder_new (GDATA_GD_REMINDER_ALERT, -1, 15);
3386 	reminder2 = gdata_gd_reminder_new (GDATA_GD_REMINDER_ALERT, -1, 15);
3387 	ASSERT_COMPARISON(==);
3388 
3389 	/* Different methods, same time type, same time. */
3390 	gdata_gd_reminder_set_method (reminder1, GDATA_GD_REMINDER_SMS);
3391 	ASSERT_COMPARISON(>);
3392 
3393 	/* Same method, different time type, same time. */
3394 	gdata_gd_reminder_set_method (reminder1, GDATA_GD_REMINDER_ALERT);
3395 	gdata_gd_reminder_set_relative_time (reminder1, -1);
3396 	gdata_gd_reminder_set_absolute_time (reminder1, 5);
3397 	ASSERT_COMPARISON(>);
3398 
3399 	/* Same method, same time type, different time. */
3400 	gdata_gd_reminder_set_absolute_time (reminder1, -1);
3401 	gdata_gd_reminder_set_relative_time (reminder1, 20);
3402 	ASSERT_COMPARISON(>);
3403 
3404 	g_object_unref (reminder2);
3405 	g_object_unref (reminder1);
3406 
3407 #undef ASSERT_COMPARISON
3408 }
3409 
3410 static void
test_gd_when(void)3411 test_gd_when (void)
3412 {
3413 	GDataGDWhen *when, *when2;
3414 	GDataGDReminder *reminder;
3415 	GList *reminders;
3416 	gint64 _time, _time2;
3417 	GError *error = NULL;
3418 	const gchar *content_type;
3419 
3420 	when = GDATA_GD_WHEN (gdata_parsable_new_from_xml (GDATA_TYPE_GD_WHEN,
3421 		"<gd:when xmlns:gd='http://schemas.google.com/g/2005' startTime='2005-06-06T17:00:00-08:00' endTime='2005-06-06T18:00:00-08:00'/>",
3422 		-1, &error));
3423 	g_assert_no_error (error);
3424 	g_assert (GDATA_IS_GD_WHEN (when));
3425 	g_clear_error (&error);
3426 
3427 	/* Check the properties */
3428 	_time = gdata_gd_when_get_start_time (when);
3429 	g_assert_cmpint (_time, ==, 1118106000);
3430 	_time2 = gdata_gd_when_get_end_time (when);
3431 	g_assert_cmpint (_time2, ==, 1118109600);
3432 	g_assert (gdata_gd_when_is_date (when) == FALSE);
3433 	g_assert (gdata_gd_when_get_value_string (when) == NULL);
3434 	g_assert (gdata_gd_when_get_reminders (when) == NULL);
3435 
3436 	/* Compare it against another identical time */
3437 	when2 = gdata_gd_when_new (_time, _time2, FALSE);
3438 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (when), GDATA_COMPARABLE (when2)), ==, 0);
3439 
3440 	/* …and a different one */
3441 	_time2 = 100;
3442 	gdata_gd_when_set_end_time (when2, _time2);
3443 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (when), GDATA_COMPARABLE (when2)), !=, 0);
3444 	g_object_unref (when2);
3445 
3446 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (when));
3447 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3448 
3449 	/* Check the outputted XML is the same */
3450 	gdata_test_assert_xml (when,
3451 			 "<?xml version='1.0' encoding='UTF-8'?>"
3452 			 "<gd:when xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' startTime='2005-06-07T01:00:00Z' "
3453 				"endTime='2005-06-07T02:00:00Z'/>");
3454 	g_object_unref (when);
3455 
3456 	/* Now parse a time with different information */
3457 	when = GDATA_GD_WHEN (gdata_parsable_new_from_xml (GDATA_TYPE_GD_WHEN,
3458 		"<gd:when xmlns:gd='http://schemas.google.com/g/2005' startTime='2005-06-06' endTime='2005-06-08' valueString='This weekend'>"
3459 			"<gd:reminder minutes='15'/>"
3460 			"<foobar/>"
3461 		"</gd:when>", -1, &error));
3462 	g_assert_no_error (error);
3463 	g_assert (GDATA_IS_GD_WHEN (when));
3464 	g_clear_error (&error);
3465 
3466 	/* Check the properties */
3467 	_time = gdata_gd_when_get_start_time (when);
3468 	g_assert_cmpint (_time, ==, 1118016000);
3469 	_time2 = gdata_gd_when_get_end_time (when);
3470 	g_assert_cmpint (_time2, ==, 1118188800);
3471 	g_assert (gdata_gd_when_is_date (when) == TRUE);
3472 	g_assert_cmpstr (gdata_gd_when_get_value_string (when), ==, "This weekend");
3473 
3474 	reminders = gdata_gd_when_get_reminders (when);
3475 	g_assert (reminders != NULL);
3476 	g_assert (GDATA_IS_GD_REMINDER (reminders->data));
3477 	g_assert (reminders->next == NULL);
3478 	g_assert (gdata_gd_reminder_is_absolute_time (GDATA_GD_REMINDER (reminders->data)) == FALSE);
3479 	g_assert_cmpint (gdata_gd_reminder_get_relative_time (GDATA_GD_REMINDER (reminders->data)), ==, 15);
3480 
3481 	/* Add another reminder */
3482 	reminder = gdata_gd_reminder_new (GDATA_GD_REMINDER_ALERT, _time, -1);
3483 	gdata_gd_when_add_reminder (when, reminder);
3484 	g_object_unref (reminder);
3485 
3486 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (when));
3487 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3488 
3489 	/* Check the outputted XML is correct */
3490 	gdata_test_assert_xml (when,
3491 			 "<?xml version='1.0' encoding='UTF-8'?>"
3492 			 "<gd:when xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' startTime='2005-06-06' "
3493 				"endTime='2005-06-08' valueString='This weekend'>"
3494 				"<gd:reminder minutes='15'/>"
3495 				"<gd:reminder absoluteTime='2005-06-06T00:00:00Z' method='alert'/>"
3496 				"<foobar/>"
3497 			 "</gd:when>");
3498 	g_object_unref (when);
3499 }
3500 
3501 static void
test_gd_when_escaping(void)3502 test_gd_when_escaping (void)
3503 {
3504 	GDataGDWhen *when;
3505 	GTimeVal start_time;
3506 
3507 	g_time_val_from_iso8601 ("2005-06-07T01:00:00Z", &start_time);
3508 	when = gdata_gd_when_new (start_time.tv_sec, -1, FALSE);
3509 	gdata_gd_when_set_value_string (when, "Value string & stuff!");
3510 
3511 	/* Check the outputted XML is escaped properly */
3512 	gdata_test_assert_xml (when,
3513 	                 "<?xml version='1.0' encoding='UTF-8'?>"
3514 	                 "<gd:when xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
3515 	                          "startTime='2005-06-07T01:00:00Z' valueString='Value string &amp; stuff!'/>");
3516 	g_object_unref (when);
3517 }
3518 
3519 static void
test_gd_when_comparison(void)3520 test_gd_when_comparison (void)
3521 {
3522 	GDataGDWhen *when1, *when2;
3523 
3524 	/* Whens are non-equal if one is a date and the other isn't, if their start times differ, or if their end times differ. */
3525 	when1 = gdata_gd_when_new (0, 1000, FALSE);
3526 	when2 = gdata_gd_when_new (0, 1000, FALSE);
3527 
3528 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (when1), GDATA_COMPARABLE (when2)), ==, 0);
3529 
3530 	/* Different date/time type. */
3531 	gdata_gd_when_set_is_date (when1, TRUE);
3532 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (when1), GDATA_COMPARABLE (when2)), !=, 0);
3533 
3534 	/* Different start time. */
3535 	gdata_gd_when_set_is_date (when1, FALSE);
3536 	gdata_gd_when_set_start_time (when1, 500);
3537 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (when1), GDATA_COMPARABLE (when2)), !=, 0);
3538 
3539 	/* Different end time. */
3540 	gdata_gd_when_set_start_time (when1, 0);
3541 	gdata_gd_when_set_end_time (when1, 15000);
3542 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (when1), GDATA_COMPARABLE (when2)), !=, 0);
3543 
3544 	g_object_unref (when2);
3545 	g_object_unref (when1);
3546 }
3547 
3548 static void
test_gd_where(void)3549 test_gd_where (void)
3550 {
3551 	GDataGDWhere *where, *where2;
3552 	GError *error = NULL;
3553 	const gchar *content_type;
3554 
3555 	where = GDATA_GD_WHERE (gdata_parsable_new_from_xml (GDATA_TYPE_GD_WHERE,
3556 		"<gd:where xmlns:gd='http://schemas.google.com/g/2005' rel='http://schemas.google.com/g/2005#event.alternate' "
3557 			"label='New York Location &lt;videoconference&gt;' valueString='Metropolis'/>", -1, &error));
3558 	g_assert_no_error (error);
3559 	g_assert (GDATA_IS_GD_WHERE (where));
3560 	g_clear_error (&error);
3561 
3562 	/* Check the properties */
3563 	g_assert_cmpstr (gdata_gd_where_get_relation_type (where), ==, GDATA_GD_WHERE_EVENT_ALTERNATE);
3564 	g_assert_cmpstr (gdata_gd_where_get_value_string (where), ==, "Metropolis");
3565 	g_assert_cmpstr (gdata_gd_where_get_label (where), ==, "New York Location <videoconference>");
3566 
3567 	/* Compare it against another identical place */
3568 	where2 = gdata_gd_where_new (GDATA_GD_WHERE_EVENT_ALTERNATE, "Metropolis", "New York Location <videoconference>");
3569 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (where), GDATA_COMPARABLE (where2)), ==, 0);
3570 
3571 	/* …and a different one */
3572 	gdata_gd_where_set_label (where2, "Atlas Mountains");
3573 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (where), GDATA_COMPARABLE (where2)), !=, 0);
3574 	g_object_unref (where2);
3575 
3576 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (where));
3577 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3578 
3579 	/* Check the outputted XML is the same */
3580 	gdata_test_assert_xml (where,
3581 			 "<?xml version='1.0' encoding='UTF-8'?>"
3582 			 "<gd:where xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
3583 				"label='New York Location &lt;videoconference&gt;' rel='http://schemas.google.com/g/2005#event.alternate' "
3584 				"valueString='Metropolis'/>");
3585 	g_object_unref (where);
3586 
3587 	/* Now parse a place with less information available */
3588 	where = GDATA_GD_WHERE (gdata_parsable_new_from_xml (GDATA_TYPE_GD_WHERE,
3589 		"<gd:where xmlns:gd='http://schemas.google.com/g/2005' valueString='Google Cafeteria &lt;Building 40&gt;'/>", -1, &error));
3590 	g_assert_no_error (error);
3591 	g_assert (GDATA_IS_GD_WHERE (where));
3592 	g_clear_error (&error);
3593 
3594 	/* Check the properties */
3595 	g_assert_cmpstr (gdata_gd_where_get_value_string (where), ==, "Google Cafeteria <Building 40>");
3596 	g_assert (gdata_gd_where_get_relation_type (where) == NULL);
3597 	g_assert (gdata_gd_where_get_label (where) == NULL);
3598 
3599 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (where));
3600 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3601 
3602 	/* Check the outputted XML contains the unknown XML */
3603 	gdata_test_assert_xml (where,
3604 			 "<?xml version='1.0' encoding='UTF-8'?>"
3605 			 "<gd:where xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
3606 				"valueString='Google Cafeteria &lt;Building 40&gt;'/>");
3607 	g_object_unref (where);
3608 }
3609 
3610 static void
test_gd_where_escaping(void)3611 test_gd_where_escaping (void)
3612 {
3613 	GDataGDWhere *where;
3614 
3615 	where = gdata_gd_where_new (GDATA_GD_WHERE_EVENT "?foo&bar", "Value string & stuff!", "<label>");
3616 
3617 	/* Check the outputted XML is escaped properly */
3618 	gdata_test_assert_xml (where,
3619 	                 "<?xml version='1.0' encoding='UTF-8'?>"
3620 	                 "<gd:where xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
3621 	                           "label='&lt;label&gt;' rel='http://schemas.google.com/g/2005#event?foo&amp;bar' "
3622 	                           "valueString='Value string &amp; stuff!'/>");
3623 	g_object_unref (where);
3624 }
3625 
3626 static void
test_gd_where_comparison(void)3627 test_gd_where_comparison (void)
3628 {
3629 	GDataGDWhere *where1, *where2;
3630 
3631 	/* Wheres differ if their value or their label differs. */
3632 	where1 = gdata_gd_where_new (NULL, "Value", "Label");
3633 	where2 = gdata_gd_where_new (GDATA_GD_WHERE_EVENT, "Value", "Label");
3634 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (where1), GDATA_COMPARABLE (where2)), ==, 0);
3635 
3636 	/* Different values. */
3637 	gdata_gd_where_set_value_string (where1, "Different");
3638 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (where1), GDATA_COMPARABLE (where2)), !=, 0);
3639 
3640 	/* Different labels. */
3641 	gdata_gd_where_set_value_string (where1, "Value");
3642 	gdata_gd_where_set_label (where1, "Different");
3643 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (where1), GDATA_COMPARABLE (where2)), !=, 0);
3644 
3645 	g_object_unref (where2);
3646 	g_object_unref (where1);
3647 }
3648 
3649 static void
test_gd_who(void)3650 test_gd_who (void)
3651 {
3652 	GDataGDWho *who, *who2;
3653 	GError *error = NULL;
3654 	const gchar *content_type;
3655 
3656 	who = GDATA_GD_WHO (gdata_parsable_new_from_xml (GDATA_TYPE_GD_WHO,
3657 		"<gd:who xmlns:gd='http://schemas.google.com/g/2005' rel='http://schemas.google.com/g/2005#message.to' valueString='Elizabeth' "
3658 			"email='liz@example.com'/>", -1, &error));
3659 	g_assert_no_error (error);
3660 	g_assert (GDATA_IS_GD_WHO (who));
3661 	g_clear_error (&error);
3662 
3663 	/* Check the properties */
3664 	g_assert_cmpstr (gdata_gd_who_get_relation_type (who), ==, "http://schemas.google.com/g/2005#message.to");
3665 	g_assert_cmpstr (gdata_gd_who_get_value_string (who), ==, "Elizabeth");
3666 	g_assert_cmpstr (gdata_gd_who_get_email_address (who), ==, "liz@example.com");
3667 
3668 	/* Compare it against another identical person */
3669 	who2 = gdata_gd_who_new ("http://schemas.google.com/g/2005#message.to", "Elizabeth", "liz@example.com");
3670 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (who), GDATA_COMPARABLE (who2)), ==, 0);
3671 
3672 	/* …and a different one */
3673 	gdata_gd_who_set_email_address (who2, "john@example.com");
3674 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (who), GDATA_COMPARABLE (who2)), !=, 0);
3675 	g_object_unref (who2);
3676 
3677 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (who));
3678 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3679 
3680 	/* Check the outputted XML is the same */
3681 	gdata_test_assert_xml (who,
3682 			 "<?xml version='1.0' encoding='UTF-8'?>"
3683 			 "<gd:who xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' email='liz@example.com' "
3684 				"rel='http://schemas.google.com/g/2005#message.to' valueString='Elizabeth'/>");
3685 	g_object_unref (who);
3686 
3687 	/* Now parse a place with less information available */
3688 	who = GDATA_GD_WHO (gdata_parsable_new_from_xml (GDATA_TYPE_GD_WHO,
3689 		"<gd:who xmlns:gd='http://schemas.google.com/g/2005'/>", -1, &error));
3690 	g_assert_no_error (error);
3691 	g_assert (GDATA_IS_GD_WHO (who));
3692 	g_clear_error (&error);
3693 
3694 	/* Check the properties */
3695 	g_assert (gdata_gd_who_get_value_string (who) == NULL);
3696 	g_assert (gdata_gd_who_get_relation_type (who) == NULL);
3697 	g_assert (gdata_gd_who_get_email_address (who) == NULL);
3698 
3699 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (who));
3700 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3701 
3702 	/* Check the outputted XML contains the unknown XML */
3703 	gdata_test_assert_xml (who,
3704 			 "<?xml version='1.0' encoding='UTF-8'?>"
3705 			 "<gd:who xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005'/>");
3706 	g_object_unref (who);
3707 }
3708 
3709 static void
test_gd_who_escaping(void)3710 test_gd_who_escaping (void)
3711 {
3712 	GDataGDWho *who;
3713 
3714 	who = gdata_gd_who_new (GDATA_GD_WHO_EVENT_ATTENDEE "?foo&bar", "Value string & stuff!", "John Smith <john.smith@gmail.com>");
3715 
3716 	/* Check the outputted XML is escaped properly */
3717 	gdata_test_assert_xml (who,
3718 	                 "<?xml version='1.0' encoding='UTF-8'?>"
3719 	                 "<gd:who xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
3720 	                         "email='John Smith &lt;john.smith@gmail.com&gt;' rel='http://schemas.google.com/g/2005#event.attendee?foo&amp;bar' "
3721 	                         "valueString='Value string &amp; stuff!'/>");
3722 	g_object_unref (who);
3723 }
3724 
3725 static void
test_gd_who_comparison(void)3726 test_gd_who_comparison (void)
3727 {
3728 	GDataGDWho *who1, *who2;
3729 
3730 	/* Whos differ if their value strings or e-mail addresses differ. */
3731 	who1 = gdata_gd_who_new (NULL, "Jo Bloggs", "email@address");
3732 	who2 = gdata_gd_who_new (GDATA_GD_WHO_EVENT_ATTENDEE, "Jo Bloggs", "email@address"); /* who knew indeed? */
3733 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (who1), GDATA_COMPARABLE (who2)), ==, 0);
3734 
3735 	/* Different value strings. */
3736 	gdata_gd_who_set_value_string (who1, "Bridget Smith");
3737 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (who1), GDATA_COMPARABLE (who2)), !=, 0);
3738 
3739 	/* Different e-mail addresses. */
3740 	gdata_gd_who_set_value_string (who1, "Jo Bloggs");
3741 	gdata_gd_who_set_email_address (who1, "foo@example.com");
3742 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (who1), GDATA_COMPARABLE (who2)), !=, 0);
3743 
3744 	g_object_unref (who2);
3745 	g_object_unref (who1);
3746 }
3747 
3748 static void
test_media_category(void)3749 test_media_category (void)
3750 {
3751 	GDataMediaCategory *category;
3752 	GError *error = NULL;
3753 	const gchar *content_type;
3754 
3755 	category = GDATA_MEDIA_CATEGORY (gdata_parsable_new_from_xml (GDATA_TYPE_MEDIA_CATEGORY,
3756 		"<media:category xmlns:media='http://search.yahoo.com/mrss/' scheme='http://dmoz.org' "
3757 			"label='Ace Ventura - Pet &amp; Detective'>Arts/Movies/Titles/A/Ace_Ventura_Series/Ace_Ventura_-_Pet_Detective"
3758 			"</media:category>", -1, &error));
3759 	g_assert_no_error (error);
3760 	g_assert (GDATA_IS_MEDIA_CATEGORY (category));
3761 	g_clear_error (&error);
3762 
3763 	/* Check the properties */
3764 	g_assert_cmpstr (gdata_media_category_get_category (category), ==, "Arts/Movies/Titles/A/Ace_Ventura_Series/Ace_Ventura_-_Pet_Detective");
3765 	g_assert_cmpstr (gdata_media_category_get_scheme (category), ==, "http://dmoz.org");
3766 	g_assert_cmpstr (gdata_media_category_get_label (category), ==, "Ace Ventura - Pet & Detective");
3767 
3768 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (category));
3769 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3770 
3771 	/* Check the outputted XML is the same */
3772 	gdata_test_assert_xml (category,
3773 			 "<?xml version='1.0' encoding='UTF-8'?>"
3774 			 "<media:category xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/' "
3775 				"scheme='http://dmoz.org' "
3776 				"label='Ace Ventura - Pet &amp; Detective'>Arts/Movies/Titles/A/Ace_Ventura_Series/Ace_Ventura_-_Pet_Detective"
3777 				"</media:category>");
3778 	g_object_unref (category);
3779 
3780 	/* Now parse one with less information available */
3781 	category = GDATA_MEDIA_CATEGORY (gdata_parsable_new_from_xml (GDATA_TYPE_MEDIA_CATEGORY,
3782 		"<media:category xmlns:media='http://search.yahoo.com/mrss/'>foo</media:category>", -1, &error));
3783 	g_assert_no_error (error);
3784 	g_assert (GDATA_IS_MEDIA_CATEGORY (category));
3785 	g_clear_error (&error);
3786 
3787 	/* Check the properties */
3788 	g_assert_cmpstr (gdata_media_category_get_category (category), ==, "foo");
3789 	g_assert_cmpstr (gdata_media_category_get_scheme (category), ==, "http://video.search.yahoo.com/mrss/category_schema");
3790 	g_assert (gdata_media_category_get_label (category) == NULL);
3791 
3792 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (category));
3793 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3794 
3795 	/* Check the outputted XML is the same */
3796 	gdata_test_assert_xml (category,
3797 			 "<?xml version='1.0' encoding='UTF-8'?>"
3798 			 "<media:category xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/' "
3799 				"scheme='http://video.search.yahoo.com/mrss/category_schema'>foo</media:category>");
3800 	g_object_unref (category);
3801 }
3802 
3803 static void
test_media_category_escaping(void)3804 test_media_category_escaping (void)
3805 {
3806 	GDataMediaCategory *category;
3807 
3808 	category = gdata_media_category_new ("<category>", "http://foo.com?foo&bar", "Label & stuff");
3809 
3810 	/* Check the outputted XML is escaped properly */
3811 	gdata_test_assert_xml (category,
3812 	                 "<?xml version='1.0' encoding='UTF-8'?>"
3813 	                 "<media:category xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/' "
3814 	                                 "scheme='http://foo.com?foo&amp;bar' label='Label &amp; stuff'>&lt;category&gt;</media:category>");
3815 	g_object_unref (category);
3816 }
3817 
3818 static void
test_media_content(void)3819 test_media_content (void)
3820 {
3821 	GDataMediaContent *content;
3822 	GError *error = NULL;
3823 	const gchar *content_type;
3824 
3825 	content = GDATA_MEDIA_CONTENT (gdata_parsable_new_from_xml (GDATA_TYPE_MEDIA_CONTENT,
3826 		"<media:content xmlns:media='http://search.yahoo.com/mrss/' url='http://www.foo.com/movie.mov' fileSize='12216320' "
3827 			"type='video/quicktime' medium='video' isDefault='true' expression='nonstop' duration='185' height='200' width='300'/>",
3828 			-1, &error));
3829 	g_assert_no_error (error);
3830 	g_assert (GDATA_IS_MEDIA_CONTENT (content));
3831 	g_clear_error (&error);
3832 
3833 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (content));
3834 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3835 
3836 	/* Check the properties */
3837 	g_assert_cmpstr (gdata_media_content_get_uri (content), ==, "http://www.foo.com/movie.mov");
3838 	g_assert_cmpint (gdata_media_content_get_filesize (content), ==, 12216320);
3839 	g_assert_cmpstr (gdata_media_content_get_content_type (content), ==, "video/quicktime");
3840 	g_assert (gdata_media_content_get_medium (content) == GDATA_MEDIA_VIDEO);
3841 	g_assert (gdata_media_content_is_default (content) == TRUE);
3842 	g_assert (gdata_media_content_get_expression (content) == GDATA_MEDIA_EXPRESSION_NONSTOP);
3843 	g_assert_cmpint (gdata_media_content_get_duration (content), ==, 185);
3844 	g_assert_cmpuint (gdata_media_content_get_width (content), ==, 300);
3845 	g_assert_cmpuint (gdata_media_content_get_height (content), ==, 200);
3846 
3847 	/* NOTE: We don't check the outputted XML, since the class currently doesn't have any support for outputting XML */
3848 	g_object_unref (content);
3849 
3850 	/* Now parse one with less information available */
3851 	content = GDATA_MEDIA_CONTENT (gdata_parsable_new_from_xml (GDATA_TYPE_MEDIA_CONTENT,
3852 		"<media:content xmlns:media='http://search.yahoo.com/mrss/' url='http://foobar.com/'/>", -1, &error));
3853 	g_assert_no_error (error);
3854 	g_assert (GDATA_IS_MEDIA_CONTENT (content));
3855 	g_clear_error (&error);
3856 
3857 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (content));
3858 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3859 
3860 	/* Check the properties */
3861 	g_assert_cmpstr (gdata_media_content_get_uri (content), ==, "http://foobar.com/");
3862 	g_assert_cmpint (gdata_media_content_get_filesize (content), ==, 0);
3863 	g_assert (gdata_media_content_get_content_type (content) == NULL);
3864 	g_assert (gdata_media_content_get_medium (content) == GDATA_MEDIA_UNKNOWN);
3865 	g_assert (gdata_media_content_is_default (content) == FALSE);
3866 	g_assert (gdata_media_content_get_expression (content) == GDATA_MEDIA_EXPRESSION_FULL);
3867 	g_assert_cmpint (gdata_media_content_get_duration (content), ==, 0);
3868 	g_assert_cmpuint (gdata_media_content_get_width (content), ==, 0);
3869 	g_assert_cmpuint (gdata_media_content_get_height (content), ==, 0);
3870 
3871 	g_object_unref (content);
3872 }
3873 
3874 static void
test_media_credit(void)3875 test_media_credit (void)
3876 {
3877 	GDataMediaCredit *credit;
3878 	GError *error = NULL;
3879 	const gchar *content_type;
3880 
3881 	credit = GDATA_MEDIA_CREDIT (gdata_parsable_new_from_xml (GDATA_TYPE_MEDIA_CREDIT,
3882 		"<media:credit xmlns:media='http://search.yahoo.com/mrss/' role='producer' scheme='urn:foobar'>entity name</media:credit>",
3883 			-1, &error));
3884 	g_assert_no_error (error);
3885 	g_assert (GDATA_IS_MEDIA_CREDIT (credit));
3886 	g_clear_error (&error);
3887 
3888 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (credit));
3889 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3890 
3891 	/* Check the properties */
3892 	g_assert_cmpstr (gdata_media_credit_get_credit (credit), ==, "entity name");
3893 	g_assert_cmpstr (gdata_media_credit_get_scheme (credit), ==, "urn:foobar");
3894 	g_assert_cmpstr (gdata_media_credit_get_role (credit), ==, "producer");
3895 
3896 	/* NOTE: We don't check the outputted XML, since the class currently doesn't have any support for outputting XML */
3897 	g_object_unref (credit);
3898 
3899 	/* Now parse one with less information available */
3900 	credit = GDATA_MEDIA_CREDIT (gdata_parsable_new_from_xml (GDATA_TYPE_MEDIA_CREDIT,
3901 		"<media:credit xmlns:media='http://search.yahoo.com/mrss/'>John Smith</media:credit>", -1, &error));
3902 	g_assert_no_error (error);
3903 	g_assert (GDATA_IS_MEDIA_CREDIT (credit));
3904 	g_clear_error (&error);
3905 
3906 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (credit));
3907 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3908 
3909 	/* Check the properties */
3910 	g_assert_cmpstr (gdata_media_credit_get_credit (credit), ==, "John Smith");
3911 	g_assert_cmpstr (gdata_media_credit_get_scheme (credit), ==, "urn:ebu");
3912 	g_assert (gdata_media_credit_get_role (credit) == NULL);
3913 
3914 	g_object_unref (credit);
3915 }
3916 
3917 #if 0
3918 /* We can't test GDataMediaGroup, since it isn't currently publicly exposed */
3919 static void
3920 test_media_group (void)
3921 {
3922 	GDataMediaGroup *group;
3923 	GList *contents, *thumbnails;
3924 	GError *error = NULL;
3925 	const gchar *content_type;
3926 
3927 	group = GDATA_MEDIA_GROUP (gdata_parsable_new_from_xml (GDATA_TYPE_MEDIA_GROUP,
3928 		"<media:group xmlns:media='http://search.yahoo.com/mrss/'>"
3929 			"<media:title>Foobar — shizzle!</media:title>"
3930 			"<media:description>This is a description, isn't it‽</media:description>"
3931 			"<media:keywords>keywords,are, fun</media:keywords>"
3932 			"<media:category scheme='http://dmoz.org' label='Ace Ventura - Pet Detective'>"
3933 				"Arts/Movies/Titles/A/Ace_Ventura_Series/Ace_Ventura_-_Pet_Detective</media:category>"
3934 			"<media:content url='http://foobar.com/'/>"
3935 			"<media:content url='http://www.foo.com/movie.mov' fileSize='12216320' type='video/quicktime' medium='video' isDefault='true' "
3936 				"expression='nonstop' duration='185' height='200' width='300'/>"
3937 			"<media:credit>John Smith</media:credit>"
3938 			"<media:player url='http://www.foo.com/player?id=1111' height='200' width='400'/>"
3939 			"<media:restriction relationship='deny'>all</media:restriction>"
3940 			"<media:restriction relationship='allow' type='country'>au us</media:restriction>"
3941 			"<media:thumbnail url='http://www.foo.com/keyframe.jpg' width='75' height='50' time='12:05:01.123'/>"
3942 			"<media:thumbnail url='http://www.foo.com/keyframe0.jpg' time='00:00:00'/>"
3943 		"</media:group>", -1, &error));
3944 	g_assert_no_error (error);
3945 	g_assert (GDATA_IS_MEDIA_GROUP (group));
3946 	g_clear_error (&error);
3947 
3948 	/* Check the properties */
3949 	g_assert_cmpstr (gdata_media_group_get_title (group), ==, "Foobar — shizzle!");
3950 	g_assert_cmpstr (gdata_media_group_get_description (group), ==, "This is a description, isn't it‽");
3951 	g_assert_cmpstr (gdata_media_group_get_keywords (group), ==, "keywords,are, fun");
3952 	g_assert (GDATA_IS_MEDIA_CATEGORY (gdata_media_group_get_category (group)));
3953 	g_assert (GDATA_IS_MEDIA_CONTENT (gdata_media_group_look_up_content (group, NULL)));
3954 	g_assert (GDATA_IS_MEDIA_CONTENT (gdata_media_group_look_up_content (group, "video/quicktime")));
3955 
3956 	contents = gdata_media_group_get_contents (group);
3957 	g_assert_cmpuint (g_list_length (contents), ==, 2);
3958 	g_assert (GDATA_IS_MEDIA_CONTENT (contents->data));
3959 	g_assert (GDATA_IS_MEDIA_CONTENT (contents->next->data));
3960 
3961 	g_assert (GDATA_IS_MEDIA_CREDIT (gdata_media_group_get_credit (group)));
3962 	g_assert_cmpstr (gdata_media_group_get_player_uri (group), ==, "http://www.foo.com/player?id=1111");
3963 	g_assert (gdata_media_group_is_restricted_in_country (group, "uk") == TRUE);
3964 	g_assert (gdata_media_group_is_restricted_in_country (group, "au") == FALSE);
3965 	g_assert (gdata_media_group_is_restricted_in_country (group, "us") == FALSE);
3966 
3967 	thumbnails = gdata_media_group_get_thumbnails (group);
3968 	g_assert_cmpuint (g_list_length (thumbnails), ==, 2);
3969 	g_assert (GDATA_IS_MEDIA_THUMBNAIL (thumbnails->data));
3970 	g_assert (GDATA_IS_MEDIA_THUMBNAIL (thumbnails->next->data));
3971 
3972 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (group));
3973 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
3974 
3975 	/* Check the outputted XML is the same */
3976 	gdata_test_assert_xml (group,
3977 			 "<?xml version='1.0' encoding='UTF-8'?>"
3978 			 "<media:group xmlns:media='http://search.yahoo.com/mrss/'>"
3979 				"<media:title>Foobar — shizzle!</media:title>"
3980 				"<media:description>This is a description, isn't it‽</media:description>"
3981 				"<media:keywords>keywords,are, fun</media:keywords>"
3982 				"<media:category scheme='http://dmoz.org' label='Ace Ventura - Pet Detective'>"
3983 					"Arts/Movies/Titles/A/Ace_Ventura_Series/Ace_Ventura_-_Pet_Detective</media:category>"
3984 				"<media:content url='http://foobar.com/'/>"
3985 				"<media:content url='http://www.foo.com/movie.mov' fileSize='12216320' type='video/quicktime' medium='video' "
3986 					"isDefault='true' expression='nonstop' duration='185' height='200' width='300'/>"
3987 				"<media:credit>John Smith</media:credit>"
3988 				"<media:player url='http://www.foo.com/player?id=1111' height='200' width='400'/>"
3989 				"<media:restriction relationship='deny'>all</media:restriction>"
3990 				"<media:restriction relationship='allow' type='country'>au us</media:restriction>"
3991 				"<media:thumbnail url='http://www.foo.com/keyframe.jpg' width='75' height='50' time='12:05:01.123'/>"
3992 				"<media:thumbnail url='http://www.foo.com/keyframe0.jpg' time='00:00:00'/>"
3993 			 "</media:group>");
3994 
3995 	/* Check setting things works */
3996 	gdata_media_group_set_title (group, "Test title");
3997 	g_assert_cmpstr (gdata_media_group_get_title (group), ==, "Test title");
3998 	gdata_media_group_set_title (group, NULL);
3999 	g_assert (gdata_media_group_get_title (group) == NULL);
4000 
4001 	gdata_media_group_set_description (group, "Foobar");
4002 	g_assert_cmpstr (gdata_media_group_get_description (group), ==, "Foobar");
4003 	gdata_media_group_set_description (group, NULL);
4004 	g_assert (gdata_media_group_get_description (group) == NULL);
4005 
4006 	gdata_media_group_set_keywords (group, "a,b, c");
4007 	g_assert_cmpstr (gdata_media_group_get_keywords (group), ==, "a,b, c");
4008 	gdata_media_group_set_keywords (group, NULL);
4009 	g_assert (gdata_media_group_get_keywords (group) == NULL);
4010 
4011 	gdata_media_group_set_category (group, NULL);
4012 	g_assert (gdata_media_group_get_category (group) == NULL);
4013 
4014 	g_object_unref (group);
4015 
4016 	/* Now parse one with less information available */
4017 	group = GDATA_MEDIA_GROUP (gdata_parsable_new_from_xml (GDATA_TYPE_MEDIA_GROUP,
4018 		"<media:group xmlns:media='http://search.yahoo.com/mrss/'></media:group>", -1, &error));
4019 	g_assert_no_error (error);
4020 	g_assert (GDATA_IS_MEDIA_GROUP (group));
4021 	g_clear_error (&error);
4022 
4023 	/* Check the properties */
4024 	g_assert (gdata_media_group_get_title (group) == NULL);
4025 	g_assert (gdata_media_group_get_description (group) == NULL);
4026 	g_assert (gdata_media_group_get_keywords (group) == NULL);
4027 	g_assert (gdata_media_group_get_category (group) == NULL);
4028 	g_assert (gdata_media_group_look_up_content (group, NULL) == NULL);
4029 	g_assert (gdata_media_group_look_up_content (group, "video/quicktime") == NULL);
4030 	g_assert (gdata_media_group_get_contents (group) == NULL);
4031 	g_assert (gdata_media_group_get_credit (group) == NULL);
4032 	g_assert (gdata_media_group_get_player_uri (group) == NULL);
4033 	g_assert (gdata_media_group_is_restricted_in_country (group, "uk") == FALSE);
4034 	g_assert (gdata_media_group_is_restricted_in_country (group, "au") == FALSE);
4035 	g_assert (gdata_media_group_is_restricted_in_country (group, "us") == FALSE);
4036 	g_assert (gdata_media_group_get_thumbnails (group) == NULL);
4037 
4038 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (group));
4039 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4040 
4041 	/* Check the outputted XML is the same */
4042 	gdata_test_assert_xml (group,
4043 		"<?xml version='1.0' encoding='UTF-8'?>"
4044 	                          "<media:group xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/'></media:group>");
4045 	g_object_unref (group);
4046 }
4047 #endif
4048 
4049 static void
test_media_thumbnail(void)4050 test_media_thumbnail (void)
4051 {
4052 	GDataMediaThumbnail *thumbnail;
4053 	GError *error = NULL;
4054 
4055 	thumbnail = GDATA_MEDIA_THUMBNAIL (gdata_parsable_new_from_xml (GDATA_TYPE_MEDIA_THUMBNAIL,
4056 		"<media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://www.foo.com/keyframe.jpg' width='75' height='50' "
4057 			"time='12:05:01.123'/>", -1, &error));
4058 	g_assert_no_error (error);
4059 	g_assert (GDATA_IS_MEDIA_THUMBNAIL (thumbnail));
4060 	g_clear_error (&error);
4061 
4062 	/* Check the properties */
4063 	g_assert_cmpstr (gdata_media_thumbnail_get_uri (thumbnail), ==, "http://www.foo.com/keyframe.jpg");
4064 	g_assert_cmpuint (gdata_media_thumbnail_get_width (thumbnail), ==, 75);
4065 	g_assert_cmpuint (gdata_media_thumbnail_get_height (thumbnail), ==, 50);
4066 	g_assert_cmpint (gdata_media_thumbnail_get_time (thumbnail), ==, 43501123);
4067 
4068 	/* NOTE: We don't check the outputted XML, since the class currently doesn't have any support for outputting XML */
4069 	g_object_unref (thumbnail);
4070 
4071 	/* Now parse one with less information available */
4072 	thumbnail = GDATA_MEDIA_THUMBNAIL (gdata_parsable_new_from_xml (GDATA_TYPE_MEDIA_THUMBNAIL,
4073 		"<media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://foobar.com/'/>", -1, &error));
4074 	g_assert_no_error (error);
4075 	g_assert (GDATA_IS_MEDIA_THUMBNAIL (thumbnail));
4076 	g_clear_error (&error);
4077 
4078 	/* Check the properties */
4079 	g_assert_cmpstr (gdata_media_thumbnail_get_uri (thumbnail), ==, "http://foobar.com/");
4080 	g_assert_cmpuint (gdata_media_thumbnail_get_width (thumbnail), ==, 0);
4081 	g_assert_cmpuint (gdata_media_thumbnail_get_height (thumbnail), ==, 0);
4082 	g_assert_cmpint (gdata_media_thumbnail_get_time (thumbnail), ==, -1);
4083 
4084 	g_object_unref (thumbnail);
4085 }
4086 
4087 static void
test_gcontact_calendar(void)4088 test_gcontact_calendar (void)
4089 {
4090 	GDataGContactCalendar *calendar, *calendar2;
4091 	GError *error = NULL;
4092 	const gchar *content_type;
4093 
4094 	calendar = GDATA_GCONTACT_CALENDAR (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_CALENDAR,
4095 		"<gContact:calendarLink xmlns:gContact='http://schemas.google.com/contact/2008' rel='work' primary='true' "
4096 			"href='http://calendar.com/'/>", -1, &error));
4097 	g_assert_no_error (error);
4098 	g_assert (GDATA_IS_GCONTACT_CALENDAR (calendar));
4099 	g_clear_error (&error);
4100 
4101 	/* Check the properties */
4102 	g_assert_cmpstr (gdata_gcontact_calendar_get_uri (calendar), ==, "http://calendar.com/");
4103 	g_assert_cmpstr (gdata_gcontact_calendar_get_relation_type (calendar), ==, GDATA_GCONTACT_CALENDAR_WORK);
4104 	g_assert (gdata_gcontact_calendar_get_label (calendar) == NULL);
4105 	g_assert (gdata_gcontact_calendar_is_primary (calendar) == TRUE);
4106 
4107 	/* Compare it against another identical calendar */
4108 	calendar2 = gdata_gcontact_calendar_new ("http://calendar.com/", GDATA_GCONTACT_CALENDAR_WORK, NULL, TRUE);
4109 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (calendar), GDATA_COMPARABLE (calendar2)), ==, 0);
4110 
4111 	/* …and a different one */
4112 	gdata_gcontact_calendar_set_uri (calendar2, "http://calendar.somewhereelse.com/");
4113 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (calendar), GDATA_COMPARABLE (calendar2)), !=, 0);
4114 	g_object_unref (calendar2);
4115 
4116 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (calendar));
4117 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4118 
4119 	/* Check the outputted XML is the same */
4120 	gdata_test_assert_xml (calendar,
4121 			 "<?xml version='1.0' encoding='UTF-8'?>"
4122 			 "<gContact:calendarLink xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4123 				"href='http://calendar.com/' rel='work' primary='true'/>");
4124 	g_object_unref (calendar);
4125 
4126 	/* Now parse a calendar with less information available */
4127 	calendar = GDATA_GCONTACT_CALENDAR (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_CALENDAR,
4128 		"<gContact:calendarLink xmlns:gContact='http://schemas.google.com/contact/2008' href='http://example.com/' label='&lt;a&gt;'/>",
4129 		-1, &error));
4130 	g_assert_no_error (error);
4131 	g_assert (GDATA_IS_GCONTACT_CALENDAR (calendar));
4132 	g_clear_error (&error);
4133 
4134 	/* Check the properties */
4135 	g_assert_cmpstr (gdata_gcontact_calendar_get_uri (calendar), ==, "http://example.com/");
4136 	g_assert (gdata_gcontact_calendar_get_relation_type (calendar) == NULL);
4137 	g_assert_cmpstr (gdata_gcontact_calendar_get_label (calendar), ==, "<a>");
4138 	g_assert (gdata_gcontact_calendar_is_primary (calendar) == FALSE);
4139 
4140 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (calendar));
4141 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4142 
4143 	/* Check the outputted XML is still OK */
4144 	gdata_test_assert_xml (calendar,
4145 			 "<?xml version='1.0' encoding='UTF-8'?>"
4146 			 "<gContact:calendarLink xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4147 				"href='http://example.com/' label='&lt;a&gt;' primary='false'/>");
4148 	g_object_unref (calendar);
4149 }
4150 
4151 static void
test_gcontact_calendar_error_handling(void)4152 test_gcontact_calendar_error_handling (void)
4153 {
4154 	GDataGContactCalendar *calendar;
4155 	GError *error = NULL;
4156 
4157 #define TEST_XML_ERROR_HANDLING(x) calendar = GDATA_GCONTACT_CALENDAR (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_CALENDAR,\
4158 		"<gContact:calendarLink xmlns:gContact='http://schemas.google.com/contact/2008' "\
4159 			x\
4160 		"/>", -1, &error));\
4161 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);\
4162 	g_assert (calendar == NULL);\
4163 	g_clear_error (&error)
4164 
4165 	TEST_XML_ERROR_HANDLING ("rel='work'"); /* no href */
4166 	TEST_XML_ERROR_HANDLING ("rel='work' href=''"); /* empty href */
4167 	TEST_XML_ERROR_HANDLING ("href='http://example.com/'"); /* no rel or label */
4168 	TEST_XML_ERROR_HANDLING ("href='http://example.com/' rel=''"); /* empty rel */
4169 	TEST_XML_ERROR_HANDLING ("href='http://example.com/' label=''"); /* empty label */
4170 	TEST_XML_ERROR_HANDLING ("href='http://example.com/' rel='other' label='Other'"); /* rel and label */
4171 	TEST_XML_ERROR_HANDLING ("href='http://example.com/' rel='home' primary='not a boolean'"); /* invalid primary */
4172 
4173 #undef TEST_XML_ERROR_HANDLING
4174 }
4175 
4176 static void
test_gcontact_calendar_escaping(void)4177 test_gcontact_calendar_escaping (void)
4178 {
4179 	GDataGContactCalendar *calendar;
4180 
4181 	/* Test with rel */
4182 	calendar = gdata_gcontact_calendar_new ("http://foo.com?foo&bar", "http://foo.com?foo&relation=bar", NULL, TRUE);
4183 
4184 	/* Check the outputted XML is escaped properly */
4185 	gdata_test_assert_xml (calendar,
4186 	                 "<?xml version='1.0' encoding='UTF-8'?>"
4187 	                 "<gContact:calendarLink xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4188 				"href='http://foo.com?foo&amp;bar' rel='http://foo.com?foo&amp;relation=bar' primary='true'/>");
4189 	g_object_unref (calendar);
4190 
4191 	/* Test with label */
4192 	calendar = gdata_gcontact_calendar_new ("http://foo.com?foo&bar", NULL, "Label & stuff", FALSE);
4193 
4194 	/* Check the outputted XML is escaped properly */
4195 	gdata_test_assert_xml (calendar,
4196 	                 "<?xml version='1.0' encoding='UTF-8'?>"
4197 	                 "<gContact:calendarLink xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4198 				"href='http://foo.com?foo&amp;bar' label='Label &amp; stuff' primary='false'/>");
4199 	g_object_unref (calendar);
4200 }
4201 
4202 static void
test_gcontact_event(void)4203 test_gcontact_event (void)
4204 {
4205 	GDataGContactEvent *event, *event2;
4206 	GDate date;
4207 	GError *error = NULL;
4208 	const gchar *content_type;
4209 
4210 	event = GDATA_GCONTACT_EVENT (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_EVENT,
4211 		"<gContact:event xmlns:gContact='http://schemas.google.com/contact/2008' xmlns:gd='http://schemas.google.com/g/2005' rel='other'>"
4212 			"<gd:when startTime='2004-03-12'/>"
4213 		"</gContact:event>", -1, &error));
4214 	g_assert_no_error (error);
4215 	g_assert (GDATA_IS_GCONTACT_EVENT (event));
4216 	g_clear_error (&error);
4217 
4218 	/* Check the properties */
4219 	gdata_gcontact_event_get_date (event, &date);
4220 	g_assert (g_date_valid (&date) == TRUE);
4221 	g_assert_cmpuint (g_date_get_year (&date), ==, 2004);
4222 	g_assert_cmpuint (g_date_get_month (&date), ==, 3);
4223 	g_assert_cmpuint (g_date_get_day (&date), ==, 12);
4224 	g_assert_cmpstr (gdata_gcontact_event_get_relation_type (event), ==, GDATA_GCONTACT_EVENT_OTHER);
4225 	g_assert (gdata_gcontact_event_get_label (event) == NULL);
4226 
4227 	/* Try creating another event from scratch */
4228 	event2 = gdata_gcontact_event_new (&date, GDATA_GCONTACT_EVENT_OTHER, NULL);
4229 	g_assert (GDATA_IS_GCONTACT_EVENT (event2));
4230 	g_object_unref (event2);
4231 
4232 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (event));
4233 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4234 
4235 	/* Check the outputted XML is the same */
4236 	gdata_test_assert_xml (event,
4237 			 "<?xml version='1.0' encoding='UTF-8'?>"
4238 			 "<gContact:event xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
4239 			   "xmlns:gContact='http://schemas.google.com/contact/2008' rel='other'>"
4240 				"<gd:when startTime='2004-03-12'/>"
4241 			 "</gContact:event>");
4242 	g_object_unref (event);
4243 
4244 	/* Now parse an event with different information available */
4245 	event = GDATA_GCONTACT_EVENT (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_EVENT,
4246 		"<gContact:event xmlns:gContact='http://schemas.google.com/contact/2008' xmlns:gd='http://schemas.google.com/g/2005' "
4247 		  "label='&lt;a&gt;'>"
4248 			"<gd:when startTime='2000-01-01'/>"
4249 		"</gContact:event>", -1, &error));
4250 	g_assert_no_error (error);
4251 	g_assert (GDATA_IS_GCONTACT_EVENT (event));
4252 	g_clear_error (&error);
4253 
4254 	/* Check the properties */
4255 	gdata_gcontact_event_get_date (event, &date);
4256 	g_assert (g_date_valid (&date) == TRUE);
4257 	g_assert_cmpuint (g_date_get_year (&date), ==, 2000);
4258 	g_assert_cmpuint (g_date_get_month (&date), ==, 1);
4259 	g_assert_cmpuint (g_date_get_day (&date), ==, 1);
4260 	g_assert (gdata_gcontact_event_get_relation_type (event) == NULL);
4261 	g_assert_cmpstr (gdata_gcontact_event_get_label (event), ==, "<a>");
4262 
4263 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (event));
4264 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4265 
4266 	/* Check the outputted XML is still OK */
4267 	gdata_test_assert_xml (event,
4268 			 "<?xml version='1.0' encoding='UTF-8'?>"
4269 			 "<gContact:event xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
4270 			   "xmlns:gContact='http://schemas.google.com/contact/2008' label='&lt;a&gt;'>"
4271 				"<gd:when startTime='2000-01-01'/>"
4272 			 "</gContact:event>");
4273 	g_object_unref (event);
4274 }
4275 
4276 static void
test_gcontact_event_error_handling(void)4277 test_gcontact_event_error_handling (void)
4278 {
4279 	GDataGContactEvent *event;
4280 	GError *error = NULL;
4281 
4282 #define TEST_XML_ERROR_HANDLING(x) event = GDATA_GCONTACT_EVENT (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_EVENT,\
4283 		"<gContact:event xmlns:gContact='http://schemas.google.com/contact/2008' xmlns:gd='http://schemas.google.com/g/2005' "\
4284 			x\
4285 		"</gContact:event>", -1, &error));\
4286 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);\
4287 	g_assert (event == NULL);\
4288 	g_clear_error (&error)
4289 
4290 	TEST_XML_ERROR_HANDLING ("rel='anniversary'>"); /* no gd:when */
4291 	TEST_XML_ERROR_HANDLING ("rel='anniversary'><gd:when/>"); /* no startTime */
4292 	TEST_XML_ERROR_HANDLING ("rel='anniversary'><gd:when startTime='foobar'/>"); /* invalid startTime */
4293 	TEST_XML_ERROR_HANDLING ("rel='anniversary'><gd:when startTime='2001-12-41'/>");
4294 	TEST_XML_ERROR_HANDLING ("rel='anniversary'><gd:when startTime='2010-03-25T22:01Z'/>");
4295 	TEST_XML_ERROR_HANDLING ("><gd:when startTime='2000-01-01'/>"); /* no rel or label */
4296 	TEST_XML_ERROR_HANDLING ("rel=''><gd:when startTime='2000-01-01'/>"); /* empty rel */
4297 	TEST_XML_ERROR_HANDLING ("label=''><gd:when startTime='2000-01-01'/>"); /* empty label */
4298 	TEST_XML_ERROR_HANDLING ("rel='other' label='Other'><gd:when startTime='2000-01-01'/>"); /* rel and label */
4299 
4300 #undef TEST_XML_ERROR_HANDLING
4301 }
4302 
4303 static void
test_gcontact_event_escaping(void)4304 test_gcontact_event_escaping (void)
4305 {
4306 	GDataGContactEvent *event;
4307 	GDate date;
4308 
4309 	g_date_clear (&date, 1);
4310 	g_date_set_dmy (&date, 1, G_DATE_JANUARY, 2011);
4311 
4312 	/* Test with rel */
4313 	event = gdata_gcontact_event_new (&date, "http://foo.com?foo&relation=bar", NULL);
4314 
4315 	/* Check the outputted XML is escaped properly */
4316 	gdata_test_assert_xml (event,
4317 	                 "<?xml version='1.0' encoding='UTF-8'?>"
4318 	                 "<gContact:event xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
4319 				"xmlns:gContact='http://schemas.google.com/contact/2008' rel='http://foo.com?foo&amp;relation=bar'>"
4320 				"<gd:when startTime='2011-01-01'/>"
4321 	                 "</gContact:event>");
4322 	g_object_unref (event);
4323 
4324 	/* Test with label */
4325 	event = gdata_gcontact_event_new (&date, NULL, "Label & stuff");
4326 
4327 	/* Check the outputted XML is escaped properly */
4328 	gdata_test_assert_xml (event,
4329 	                 "<?xml version='1.0' encoding='UTF-8'?>"
4330 	                 "<gContact:event xmlns='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005' "
4331 				"xmlns:gContact='http://schemas.google.com/contact/2008' label='Label &amp; stuff'>"
4332 				"<gd:when startTime='2011-01-01'/>"
4333 	                 "</gContact:event>");
4334 	g_object_unref (event);
4335 }
4336 
4337 static void
test_gcontact_external_id(void)4338 test_gcontact_external_id (void)
4339 {
4340 	GDataGContactExternalID *id, *id2;
4341 	GError *error = NULL;
4342 	const gchar *content_type;
4343 
4344 	id = GDATA_GCONTACT_EXTERNAL_ID (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_EXTERNAL_ID,
4345 		"<gContact:externalId xmlns:gContact='http://schemas.google.com/contact/2008' rel='account' value='5'/>", -1, &error));
4346 	g_assert_no_error (error);
4347 	g_assert (GDATA_IS_GCONTACT_EXTERNAL_ID (id));
4348 	g_clear_error (&error);
4349 
4350 	/* Check the properties */
4351 	g_assert_cmpstr (gdata_gcontact_external_id_get_value (id), ==, "5");
4352 	g_assert_cmpstr (gdata_gcontact_external_id_get_relation_type (id), ==, GDATA_GCONTACT_EXTERNAL_ID_ACCOUNT);
4353 	g_assert (gdata_gcontact_external_id_get_label (id) == NULL);
4354 
4355 	/* Compare it against another identical external ID */
4356 	id2 = gdata_gcontact_external_id_new ("5", GDATA_GCONTACT_EXTERNAL_ID_ACCOUNT, NULL);
4357 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (id), GDATA_COMPARABLE (id2)), ==, 0);
4358 
4359 	/* …and a different one */
4360 	gdata_gcontact_external_id_set_value (id2, "http://identifying.uri");
4361 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (id), GDATA_COMPARABLE (id2)), !=, 0);
4362 	g_object_unref (id2);
4363 
4364 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (id));
4365 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4366 
4367 	/* Check the outputted XML is the same */
4368 	gdata_test_assert_xml (id,
4369 			 "<?xml version='1.0' encoding='UTF-8'?>"
4370 			 "<gContact:externalId xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4371 				"value='5' rel='account'/>");
4372 	g_object_unref (id);
4373 
4374 	/* Now parse an ID with less information available */
4375 	id = GDATA_GCONTACT_EXTERNAL_ID (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_EXTERNAL_ID,
4376 		"<gContact:externalId xmlns:gContact='http://schemas.google.com/contact/2008' value='' label='&lt;a&gt;'/>", -1, &error));
4377 	g_assert_no_error (error);
4378 	g_assert (GDATA_IS_GCONTACT_EXTERNAL_ID (id));
4379 	g_clear_error (&error);
4380 
4381 	/* Check the properties */
4382 	g_assert_cmpstr (gdata_gcontact_external_id_get_value (id), ==, "");
4383 	g_assert (gdata_gcontact_external_id_get_relation_type (id) == NULL);
4384 	g_assert_cmpstr (gdata_gcontact_external_id_get_label (id), ==, "<a>");
4385 
4386 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (id));
4387 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4388 
4389 	/* Check the outputted XML is still OK */
4390 	gdata_test_assert_xml (id,
4391 			 "<?xml version='1.0' encoding='UTF-8'?>"
4392 			 "<gContact:externalId xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4393 				"value='' label='&lt;a&gt;'/>");
4394 	g_object_unref (id);
4395 }
4396 
4397 static void
test_gcontact_external_id_error_handling(void)4398 test_gcontact_external_id_error_handling (void)
4399 {
4400 	GDataGContactExternalID *id;
4401 	GError *error = NULL;
4402 
4403 #define TEST_XML_ERROR_HANDLING(x) id = GDATA_GCONTACT_EXTERNAL_ID (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_EXTERNAL_ID,\
4404 		"<gContact:externalId xmlns:gContact='http://schemas.google.com/contact/2008' "\
4405 			x\
4406 		"/>", -1, &error));\
4407 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);\
4408 	g_assert (id == NULL);\
4409 	g_clear_error (&error)
4410 
4411 	TEST_XML_ERROR_HANDLING ("rel='account'"); /* no value */
4412 	TEST_XML_ERROR_HANDLING ("value='foo'"); /* no rel or label */
4413 	TEST_XML_ERROR_HANDLING ("value='foo' rel=''"); /* empty rel */
4414 	TEST_XML_ERROR_HANDLING ("value='foo' label=''"); /* empty label */
4415 	TEST_XML_ERROR_HANDLING ("value='foo' rel='organization' label='Other'"); /* rel and label */
4416 
4417 #undef TEST_XML_ERROR_HANDLING
4418 }
4419 
4420 static void
test_gcontact_external_id_escaping(void)4421 test_gcontact_external_id_escaping (void)
4422 {
4423 	GDataGContactExternalID *id;
4424 
4425 	/* Test with rel */
4426 	id = gdata_gcontact_external_id_new ("<id>", "http://foo.com?foo&relation=bar", NULL);
4427 
4428 	/* Check the outputted XML is escaped properly */
4429 	gdata_test_assert_xml (id,
4430 	                 "<?xml version='1.0' encoding='UTF-8'?>"
4431 	                 "<gContact:externalId xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4432 				"value='&lt;id&gt;' rel='http://foo.com?foo&amp;relation=bar'/>");
4433 	g_object_unref (id);
4434 
4435 	/* Test with label */
4436 	id = gdata_gcontact_external_id_new ("<id>", NULL, "Label & stuff");
4437 
4438 	/* Check the outputted XML is escaped properly */
4439 	gdata_test_assert_xml (id,
4440 	                 "<?xml version='1.0' encoding='UTF-8'?>"
4441 	                 "<gContact:externalId xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4442 				"value='&lt;id&gt;' label='Label &amp; stuff'/>");
4443 	g_object_unref (id);
4444 }
4445 
4446 static void
test_gcontact_jot(void)4447 test_gcontact_jot (void)
4448 {
4449 	GDataGContactJot *jot, *jot2;
4450 	GError *error = NULL;
4451 	const gchar *content_type;
4452 
4453 	jot = GDATA_GCONTACT_JOT (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_JOT,
4454 		"<gContact:jot xmlns:gContact='http://schemas.google.com/contact/2008' rel='user'>They like &lt;angles&gt;.</gContact:jot>",
4455 		-1, &error));
4456 	g_assert_no_error (error);
4457 	g_assert (GDATA_IS_GCONTACT_JOT (jot));
4458 	g_clear_error (&error);
4459 
4460 	/* Check the properties */
4461 	g_assert_cmpstr (gdata_gcontact_jot_get_relation_type (jot), ==, GDATA_GCONTACT_JOT_USER);
4462 	g_assert_cmpstr (gdata_gcontact_jot_get_content (jot), ==, "They like <angles>.");
4463 
4464 	/* Try creating another jot from scratch */
4465 	jot2 = gdata_gcontact_jot_new ("friend,local,oss", GDATA_GCONTACT_JOT_KEYWORDS);
4466 	g_assert (GDATA_IS_GCONTACT_JOT (jot2));
4467 	g_object_unref (jot2);
4468 
4469 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (jot));
4470 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4471 
4472 	/* Check the outputted XML is the same */
4473 	gdata_test_assert_xml (jot,
4474 			 "<?xml version='1.0' encoding='UTF-8'?>"
4475 			 "<gContact:jot xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' rel='user'>"
4476 				"They like &lt;angles&gt;.</gContact:jot>");
4477 	g_object_unref (jot);
4478 
4479 	/* Now parse a jot with different information available */
4480 	jot = GDATA_GCONTACT_JOT (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_JOT,
4481 		"<gContact:jot xmlns:gContact='http://schemas.google.com/contact/2008' rel='other'/>", -1, &error));
4482 	g_assert_no_error (error);
4483 	g_assert (GDATA_IS_GCONTACT_JOT (jot));
4484 	g_clear_error (&error);
4485 
4486 	/* Check the properties */
4487 	g_assert_cmpstr (gdata_gcontact_jot_get_relation_type (jot), ==, GDATA_GCONTACT_JOT_OTHER);
4488 	g_assert (gdata_gcontact_jot_get_content (jot) == NULL);
4489 
4490 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (jot));
4491 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4492 
4493 	/* Check the outputted XML is still OK */
4494 	gdata_test_assert_xml (jot,
4495 			 "<?xml version='1.0' encoding='UTF-8'?>"
4496 			 "<gContact:jot xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' rel='other'/>");
4497 	g_object_unref (jot);
4498 }
4499 
4500 static void
test_gcontact_jot_error_handling(void)4501 test_gcontact_jot_error_handling (void)
4502 {
4503 	GDataGContactJot *jot;
4504 	GError *error = NULL;
4505 
4506 #define TEST_XML_ERROR_HANDLING(x) jot = GDATA_GCONTACT_JOT (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_JOT,\
4507 		"<gContact:jot xmlns:gContact='http://schemas.google.com/contact/2008' "\
4508 			x\
4509 		"</gContact:jot>", -1, &error));\
4510 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);\
4511 	g_assert (jot == NULL);\
4512 	g_clear_error (&error)
4513 
4514 	TEST_XML_ERROR_HANDLING (">Content"); /* no rel */
4515 	TEST_XML_ERROR_HANDLING ("rel=''>Content"); /* empty rel */
4516 
4517 #undef TEST_XML_ERROR_HANDLING
4518 }
4519 
4520 static void
test_gcontact_jot_escaping(void)4521 test_gcontact_jot_escaping (void)
4522 {
4523 	GDataGContactJot *jot;
4524 
4525 	jot = gdata_gcontact_jot_new ("Content & stuff", "http://foo.com?foo&relation=bar");
4526 
4527 	/* Check the outputted XML is escaped properly */
4528 	gdata_test_assert_xml (jot,
4529 	                 "<?xml version='1.0' encoding='UTF-8'?>"
4530 	                 "<gContact:jot xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4531 				"rel='http://foo.com?foo&amp;relation=bar'>Content &amp; stuff</gContact:jot>");
4532 	g_object_unref (jot);
4533 }
4534 
4535 static void
test_gcontact_language(void)4536 test_gcontact_language (void)
4537 {
4538 	GDataGContactLanguage *language, *language2;
4539 	GError *error = NULL;
4540 	const gchar *content_type;
4541 
4542 	language = GDATA_GCONTACT_LANGUAGE (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_LANGUAGE,
4543 		"<gContact:language xmlns:gContact='http://schemas.google.com/contact/2008' code='en-GB'/>", -1, &error));
4544 	g_assert_no_error (error);
4545 	g_assert (GDATA_IS_GCONTACT_LANGUAGE (language));
4546 	g_clear_error (&error);
4547 
4548 	/* Check the properties */
4549 	g_assert_cmpstr (gdata_gcontact_language_get_code (language), ==, "en-GB");
4550 	g_assert (gdata_gcontact_language_get_label (language) == NULL);
4551 
4552 	/* Compare it against another identical language */
4553 	language2 = gdata_gcontact_language_new ("en-GB", NULL);
4554 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (language), GDATA_COMPARABLE (language2)), ==, 0);
4555 
4556 	/* …and a different one */
4557 	gdata_gcontact_language_set_code (language2, "sv");
4558 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (language), GDATA_COMPARABLE (language2)), !=, 0);
4559 	g_object_unref (language2);
4560 
4561 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (language));
4562 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4563 
4564 	/* Check the outputted XML is the same */
4565 	gdata_test_assert_xml (language,
4566 			 "<?xml version='1.0' encoding='UTF-8'?>"
4567 			 "<gContact:language xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4568 				"code='en-GB'/>");
4569 	g_object_unref (language);
4570 
4571 	/* Now parse a language with less information available */
4572 	language = GDATA_GCONTACT_LANGUAGE (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_LANGUAGE,
4573 		"<gContact:language xmlns:gContact='http://schemas.google.com/contact/2008' label='Gobbledegook'/>",
4574 		-1, &error));
4575 	g_assert_no_error (error);
4576 	g_assert (GDATA_IS_GCONTACT_LANGUAGE (language));
4577 	g_clear_error (&error);
4578 
4579 	/* Check the properties */
4580 	g_assert (gdata_gcontact_language_get_code (language) == NULL);
4581 	g_assert_cmpstr (gdata_gcontact_language_get_label (language), ==, "Gobbledegook");
4582 
4583 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (language));
4584 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4585 
4586 	/* Check the outputted XML is still OK */
4587 	gdata_test_assert_xml (language,
4588 			 "<?xml version='1.0' encoding='UTF-8'?>"
4589 			 "<gContact:language xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4590 				"label='Gobbledegook'/>");
4591 	g_object_unref (language);
4592 }
4593 
4594 static void
test_gcontact_language_error_handling(void)4595 test_gcontact_language_error_handling (void)
4596 {
4597 	GDataGContactLanguage *language;
4598 	GError *error = NULL;
4599 
4600 #define TEST_XML_ERROR_HANDLING(x) language = GDATA_GCONTACT_LANGUAGE (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_LANGUAGE,\
4601 		"<gContact:language xmlns:gContact='http://schemas.google.com/contact/2008' "\
4602 			x\
4603 		"/>", -1, &error));\
4604 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);\
4605 	g_assert (language == NULL);\
4606 	g_clear_error (&error)
4607 
4608 	TEST_XML_ERROR_HANDLING (""); /* no code or label */
4609 	TEST_XML_ERROR_HANDLING ("code=''"); /* empty code */
4610 	TEST_XML_ERROR_HANDLING ("label=''"); /* empty label */
4611 	TEST_XML_ERROR_HANDLING ("code='en-GB' label='Other'"); /* code and label */
4612 
4613 #undef TEST_XML_ERROR_HANDLING
4614 }
4615 
4616 static void
test_gcontact_language_escaping(void)4617 test_gcontact_language_escaping (void)
4618 {
4619 	GDataGContactLanguage *language;
4620 
4621 	/* Test with code */
4622 	language = gdata_gcontact_language_new ("<code>", NULL);
4623 
4624 	/* Check the outputted XML is escaped properly */
4625 	gdata_test_assert_xml (language,
4626 	                 "<?xml version='1.0' encoding='UTF-8'?>"
4627 	                 "<gContact:language xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4628 				"code='&lt;code&gt;'/>");
4629 	g_object_unref (language);
4630 
4631 	/* Test with label */
4632 	language = gdata_gcontact_language_new (NULL, "Label & stuff");
4633 
4634 	/* Check the outputted XML is escaped properly */
4635 	gdata_test_assert_xml (language,
4636 	                 "<?xml version='1.0' encoding='UTF-8'?>"
4637 	                 "<gContact:language xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4638 				"label='Label &amp; stuff'/>");
4639 	g_object_unref (language);
4640 }
4641 
4642 static void
test_gcontact_relation(void)4643 test_gcontact_relation (void)
4644 {
4645 	GDataGContactRelation *relation, *relation2;
4646 	GError *error = NULL;
4647 	const gchar *content_type;
4648 
4649 	relation = GDATA_GCONTACT_RELATION (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_RELATION,
4650 		"<gContact:relation xmlns:gContact='http://schemas.google.com/contact/2008' rel='child'>Fred</gContact:relation>", -1, &error));
4651 	g_assert_no_error (error);
4652 	g_assert (GDATA_IS_GCONTACT_RELATION (relation));
4653 	g_clear_error (&error);
4654 
4655 	/* Check the properties */
4656 	g_assert_cmpstr (gdata_gcontact_relation_get_name (relation), ==, "Fred");
4657 	g_assert_cmpstr (gdata_gcontact_relation_get_relation_type (relation), ==, GDATA_GCONTACT_RELATION_CHILD);
4658 	g_assert (gdata_gcontact_relation_get_label (relation) == NULL);
4659 
4660 	/* Try creating another relation from scratch */
4661 	relation2 = gdata_gcontact_relation_new ("Brian", GDATA_GCONTACT_RELATION_RELATIVE, NULL);
4662 	g_assert (GDATA_IS_GCONTACT_RELATION (relation2));
4663 	g_object_unref (relation2);
4664 
4665 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (relation));
4666 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4667 
4668 	/* Check the outputted XML is the same */
4669 	gdata_test_assert_xml (relation,
4670 			 "<?xml version='1.0' encoding='UTF-8'?>"
4671 			 "<gContact:relation xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' rel='child'>"
4672 				"Fred</gContact:relation>");
4673 	g_object_unref (relation);
4674 
4675 	/* Now parse a relation with different information available */
4676 	relation = GDATA_GCONTACT_RELATION (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_RELATION,
4677 		"<gContact:relation xmlns:gContact='http://schemas.google.com/contact/2008' label='&lt;a&gt;'>Sid</gContact:relation>", -1, &error));
4678 	g_assert_no_error (error);
4679 	g_assert (GDATA_IS_GCONTACT_RELATION (relation));
4680 	g_clear_error (&error);
4681 
4682 	/* Check the properties */
4683 	g_assert_cmpstr (gdata_gcontact_relation_get_name (relation), ==, "Sid");
4684 	g_assert (gdata_gcontact_relation_get_relation_type (relation) == NULL);
4685 	g_assert_cmpstr (gdata_gcontact_relation_get_label (relation), ==, "<a>");
4686 
4687 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (relation));
4688 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4689 
4690 	/* Check the outputted XML is still OK */
4691 	gdata_test_assert_xml (relation,
4692 			 "<?xml version='1.0' encoding='UTF-8'?>"
4693 			 "<gContact:relation xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4694 			   "label='&lt;a&gt;'>Sid</gContact:relation>");
4695 	g_object_unref (relation);
4696 }
4697 
4698 static void
test_gcontact_relation_error_handling(void)4699 test_gcontact_relation_error_handling (void)
4700 {
4701 	GDataGContactRelation *relation;
4702 	GError *error = NULL;
4703 
4704 #define TEST_XML_ERROR_HANDLING(x) relation = GDATA_GCONTACT_RELATION (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_RELATION,\
4705 		"<gContact:relation xmlns:gContact='http://schemas.google.com/contact/2008' "\
4706 			x\
4707 		"</gContact:relation>", -1, &error));\
4708 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);\
4709 	g_assert (relation == NULL);\
4710 	g_clear_error (&error)
4711 
4712 	TEST_XML_ERROR_HANDLING ("rel='spouse'>"); /* no name */
4713 	TEST_XML_ERROR_HANDLING (">Brian"); /* no rel or label */
4714 	TEST_XML_ERROR_HANDLING ("rel=''>Brian"); /* empty rel */
4715 	TEST_XML_ERROR_HANDLING ("label=''>Brian"); /* empty label */
4716 	TEST_XML_ERROR_HANDLING ("rel='sister' label='Older sister'>Brian"); /* rel and label */
4717 
4718 #undef TEST_XML_ERROR_HANDLING
4719 }
4720 
4721 static void
test_gcontact_relation_escaping(void)4722 test_gcontact_relation_escaping (void)
4723 {
4724 	GDataGContactRelation *relation;
4725 
4726 	/* Test with rel */
4727 	relation = gdata_gcontact_relation_new ("First & Last Name", "http://foo.com?foo&relation=bar", NULL);
4728 
4729 	/* Check the outputted XML is escaped properly */
4730 	gdata_test_assert_xml (relation,
4731 	                 "<?xml version='1.0' encoding='UTF-8'?>"
4732 	                 "<gContact:relation xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4733 				"rel='http://foo.com?foo&amp;relation=bar'>First &amp; Last Name</gContact:relation>");
4734 	g_object_unref (relation);
4735 
4736 	/* Test with label */
4737 	relation = gdata_gcontact_relation_new ("First & Last Name", NULL, "Label & stuff");
4738 
4739 	/* Check the outputted XML is escaped properly */
4740 	gdata_test_assert_xml (relation,
4741 	                 "<?xml version='1.0' encoding='UTF-8'?>"
4742 	                 "<gContact:relation xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4743 				"label='Label &amp; stuff'>First &amp; Last Name</gContact:relation>");
4744 	g_object_unref (relation);
4745 }
4746 
4747 static void
test_gcontact_website(void)4748 test_gcontact_website (void)
4749 {
4750 	GDataGContactWebsite *website, *website2;
4751 	GError *error = NULL;
4752 	const gchar *content_type;
4753 
4754 	website = GDATA_GCONTACT_WEBSITE (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_WEBSITE,
4755 		"<gContact:website xmlns:gContact='http://schemas.google.com/contact/2008' href='http://example.com/' rel='work' primary='true' "
4756 			"label='&lt;Markup&gt; blog'/>", -1, &error));
4757 	g_assert_no_error (error);
4758 	g_assert (GDATA_IS_GCONTACT_WEBSITE (website));
4759 	g_clear_error (&error);
4760 
4761 	/* Check the properties */
4762 	g_assert_cmpstr (gdata_gcontact_website_get_uri (website), ==, "http://example.com/");
4763 	g_assert_cmpstr (gdata_gcontact_website_get_relation_type (website), ==, GDATA_GCONTACT_WEBSITE_WORK);
4764 	g_assert_cmpstr (gdata_gcontact_website_get_label (website), ==, "<Markup> blog");
4765 	g_assert (gdata_gcontact_website_is_primary (website) == TRUE);
4766 
4767 	/* Compare it against another identical website */
4768 	website2 = gdata_gcontact_website_new ("http://example.com/", GDATA_GCONTACT_WEBSITE_WORK, "<Markup> blog", TRUE);
4769 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (website), GDATA_COMPARABLE (website2)), ==, 0);
4770 
4771 	/* …and a different one */
4772 	gdata_gcontact_website_set_uri (website2, "http://somewhereelse.com/");
4773 	g_assert_cmpint (gdata_comparable_compare (GDATA_COMPARABLE (website), GDATA_COMPARABLE (website2)), !=, 0);
4774 	g_object_unref (website2);
4775 
4776 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (website));
4777 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4778 
4779 	/* Check the outputted XML is the same */
4780 	gdata_test_assert_xml (website,
4781 			 "<?xml version='1.0' encoding='UTF-8'?>"
4782 			 "<gContact:website xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4783 				"href='http://example.com/' rel='work' label='&lt;Markup&gt; blog' primary='true'/>");
4784 	g_object_unref (website);
4785 
4786 	/* Now parse a website with less information available */
4787 	website = GDATA_GCONTACT_WEBSITE (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_WEBSITE,
4788 		"<gContact:website xmlns:gContact='http://schemas.google.com/contact/2008' href='http://test.com/' rel='ftp'/>", -1, &error));
4789 	g_assert_no_error (error);
4790 	g_assert (GDATA_IS_GCONTACT_WEBSITE (website));
4791 	g_clear_error (&error);
4792 
4793 	/* Check the properties */
4794 	g_assert_cmpstr (gdata_gcontact_website_get_uri (website), ==, "http://test.com/");
4795 	g_assert_cmpstr (gdata_gcontact_website_get_relation_type (website), ==, GDATA_GCONTACT_WEBSITE_FTP);
4796 	g_assert (gdata_gcontact_website_get_label (website) == NULL);
4797 	g_assert (gdata_gcontact_website_is_primary (website) == FALSE);
4798 
4799 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (website));
4800 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4801 
4802 	/* Check the outputted XML is still OK */
4803 	gdata_test_assert_xml (website,
4804 			 "<?xml version='1.0' encoding='UTF-8'?>"
4805 			 "<gContact:website xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4806 				"href='http://test.com/' rel='ftp' primary='false'/>");
4807 	g_object_unref (website);
4808 }
4809 
4810 static void
test_gcontact_website_label(void)4811 test_gcontact_website_label (void)
4812 {
4813 	GDataGContactWebsite *website;
4814 	GError *error = NULL;
4815 	const gchar *content_type;
4816 
4817 	g_test_bug ("659016");
4818 
4819 	/* Parse a website with a label but no rel. */
4820 	website = GDATA_GCONTACT_WEBSITE (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_WEBSITE,
4821 		"<gContact:website xmlns:gContact='http://schemas.google.com/contact/2008' href='http://test.com/' label='Custom'/>", -1, &error));
4822 	g_assert_no_error (error);
4823 	g_assert (GDATA_IS_GCONTACT_WEBSITE (website));
4824 	g_clear_error (&error);
4825 
4826 	/* Check the properties */
4827 	g_assert_cmpstr (gdata_gcontact_website_get_uri (website), ==, "http://test.com/");
4828 	g_assert_cmpstr (gdata_gcontact_website_get_relation_type (website), ==, NULL);
4829 	g_assert_cmpstr (gdata_gcontact_website_get_label (website), ==, "Custom");
4830 	g_assert (gdata_gcontact_website_is_primary (website) == FALSE);
4831 
4832 	content_type = gdata_parsable_get_content_type (GDATA_PARSABLE (website));
4833 	g_assert_cmpstr (content_type, ==, "application/atom+xml");
4834 
4835 	/* Check the outputted XML is still OK */
4836 	gdata_test_assert_xml (website,
4837 		"<?xml version='1.0' encoding='UTF-8'?>"
4838 		"<gContact:website xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4839 		                  "href='http://test.com/' label='Custom' primary='false'/>");
4840 	g_object_unref (website);
4841 }
4842 
4843 static void
test_gcontact_website_error_handling(void)4844 test_gcontact_website_error_handling (void)
4845 {
4846 	GDataGContactWebsite *website;
4847 	GError *error = NULL;
4848 
4849 #define TEST_XML_ERROR_HANDLING(x) website = GDATA_GCONTACT_WEBSITE (gdata_parsable_new_from_xml (GDATA_TYPE_GCONTACT_WEBSITE,\
4850 		"<gContact:website xmlns:gContact='http://schemas.google.com/contact/2008' "\
4851 			x\
4852 		"/>", -1, &error));\
4853 	g_assert_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR);\
4854 	g_assert (website == NULL);\
4855 	g_clear_error (&error)
4856 
4857 	TEST_XML_ERROR_HANDLING ("rel='work'"); /* no href */
4858 	TEST_XML_ERROR_HANDLING ("rel='work' href=''"); /* empty href */
4859 	TEST_XML_ERROR_HANDLING ("href='http://example.com/'"); /* no rel or label */
4860 	TEST_XML_ERROR_HANDLING ("href='http://example.com/' rel=''"); /* empty rel */
4861 	TEST_XML_ERROR_HANDLING ("href='http://example.com/' rel='profile' primary='not a boolean'"); /* invalid primary */
4862 
4863 #undef TEST_XML_ERROR_HANDLING
4864 }
4865 
4866 static void
test_gcontact_website_escaping(void)4867 test_gcontact_website_escaping (void)
4868 {
4869 	GDataGContactWebsite *website;
4870 
4871 	website = gdata_gcontact_website_new ("http://foo.com?foo&bar", "http://foo.com?foo&relation=bar", "Label & stuff", TRUE);
4872 
4873 	/* Check the outputted XML is escaped properly */
4874 	gdata_test_assert_xml (website,
4875 	                 "<?xml version='1.0' encoding='UTF-8'?>"
4876 	                 "<gContact:website xmlns='http://www.w3.org/2005/Atom' xmlns:gContact='http://schemas.google.com/contact/2008' "
4877 				"href='http://foo.com?foo&amp;bar' rel='http://foo.com?foo&amp;relation=bar' label='Label &amp; stuff' "
4878 				"primary='true'/>");
4879 	g_object_unref (website);
4880 }
4881 
4882 int
main(int argc,char * argv[])4883 main (int argc, char *argv[])
4884 {
4885 	gdata_test_init (argc, argv);
4886 
4887 	g_test_add_func ("/tests/xml_comparison", test_xml_comparison);
4888 
4889 	g_test_add_func ("/service/network_error", test_service_network_error);
4890 	g_test_add_func ("/service/locale", test_service_locale);
4891 
4892 	g_test_add_func ("/entry/get_xml", test_entry_get_xml);
4893 	g_test_add_func ("/entry/get_json", test_entry_get_json);
4894 	g_test_add_func ("/entry/parse_xml", test_entry_parse_xml);
4895 	g_test_add_func ("/entry/parse_xml/kind_category", test_entry_parse_xml_kind_category);
4896 	g_test_add_func ("/entry/parse_json", test_entry_parse_json);
4897 	g_test_add_func ("/entry/error_handling/xml", test_entry_error_handling_xml);
4898 	g_test_add_func ("/entry/error_handling/json", test_entry_error_handling_json);
4899 	g_test_add_func ("/entry/escaping", test_entry_escaping);
4900 	g_test_add_func ("/entry/links/remove", test_entry_links_remove);
4901 
4902 	g_test_add_func ("/feed/parse_xml", test_feed_parse_xml);
4903 	g_test_add_func ("/feed/error_handling", test_feed_error_handling);
4904 	g_test_add_func ("/feed/escaping", test_feed_escaping);
4905 
4906 	g_test_add_func ("/query/categories", test_query_categories);
4907 	g_test_add_func ("/query/dates", test_query_dates);
4908 	g_test_add_func ("/query/strict", test_query_strict);
4909 	g_test_add_func ("/query/pagination", test_query_pagination);
4910 	g_test_add_func ("/query/properties", test_query_properties);
4911 	g_test_add_func ("/query/unicode", test_query_unicode);
4912 	g_test_add_func ("/query/etag", test_query_etag);
4913 
4914 	g_test_add_func ("/access-rule/get_xml", test_access_rule_get_xml);
4915 	g_test_add_func ("/access-rule/get_xml/with_key", test_access_rule_get_xml_with_key);
4916 	g_test_add_func ("/access-rule/error_handling", test_access_rule_error_handling);
4917 	g_test_add_func ("/access-rule/escaping", test_access_rule_escaping);
4918 
4919 	g_test_add_func ("/comparable", test_comparable);
4920 
4921 	g_test_add_func ("/color/parsing", test_color_parsing);
4922 	g_test_add_func ("/color/output", test_color_output);
4923 
4924 	g_test_add_func ("/atom/author", test_atom_author);
4925 	g_test_add_func ("/atom/author/error_handling", test_atom_author_error_handling);
4926 	g_test_add_func ("/atom/author/escaping", test_atom_author_escaping);
4927 	g_test_add_func ("/atom/category", test_atom_category);
4928 	g_test_add_func ("/atom/category/error_handling", test_atom_category_error_handling);
4929 	g_test_add_func ("/atom/category/escaping", test_atom_category_escaping);
4930 	g_test_add_func ("/atom/generator", test_atom_generator);
4931 	g_test_add_func ("/atom/generator/error_handling", test_atom_generator_error_handling);
4932 	g_test_add_func ("/atom/link", test_atom_link);
4933 	g_test_add_func ("/atom/link/error_handling", test_atom_link_error_handling);
4934 	g_test_add_func ("/atom/link/escaping", test_atom_link_escaping);
4935 
4936 	g_test_add_func ("/app/categories", test_app_categories);
4937 
4938 	g_test_add_func ("/gd/email_address", test_gd_email_address);
4939 	g_test_add_func ("/gd/email_address/escaping", test_gd_email_address_escaping);
4940 	g_test_add_func ("/gd/email_address/comparison", test_gd_email_address_comparison);
4941 	g_test_add_func ("/gd/im_address", test_gd_im_address);
4942 	g_test_add_func ("/gd/im_address/escaping", test_gd_im_address_escaping);
4943 	g_test_add_func ("/gd/im_address/comparison", test_gd_im_address_comparison);
4944 	g_test_add_func ("/gd/name", test_gd_name);
4945 	g_test_add_func ("/gd/name/empty_strings", test_gd_name_empty_strings);
4946 	g_test_add_func ("/gd/name/comparison", test_gd_name_comparison);
4947 	g_test_add_func ("/gd/organization", test_gd_organization);
4948 	g_test_add_func ("/gd/organization/escaping", test_gd_organization_escaping);
4949 	g_test_add_func ("/gd/organization/comparison", test_gd_organization_comparison);
4950 	g_test_add_func ("/gd/phone_number", test_gd_phone_number);
4951 	g_test_add_func ("/gd/phone_number/escaping", test_gd_phone_number_escaping);
4952 	g_test_add_func ("/gd/phone_number/comparison", test_gd_phone_number_comparison);
4953 	g_test_add_func ("/gd/postal_address", test_gd_postal_address);
4954 	g_test_add_func ("/gd/postal_address/escaping", test_gd_postal_address_escaping);
4955 	g_test_add_func ("/gd/postal_address/comparison", test_gd_postal_address_comparison);
4956 	g_test_add_func ("/gd/reminder", test_gd_reminder);
4957 	g_test_add_func ("/gd/reminder/escaping", test_gd_reminder_escaping);
4958 	g_test_add_func ("/gd/reminder/comparison", test_gd_reminder_comparison);
4959 	g_test_add_func ("/gd/when", test_gd_when);
4960 	g_test_add_func ("/gd/when/escaping", test_gd_when_escaping);
4961 	g_test_add_func ("/gd/when/comparison", test_gd_when_comparison);
4962 	g_test_add_func ("/gd/where", test_gd_where);
4963 	g_test_add_func ("/gd/where/escaping", test_gd_where_escaping);
4964 	g_test_add_func ("/gd/where/comparison", test_gd_where_comparison);
4965 	g_test_add_func ("/gd/who", test_gd_who);
4966 	g_test_add_func ("/gd/who/escaping", test_gd_who_escaping);
4967 	g_test_add_func ("/gd/who/comparison", test_gd_who_comparison);
4968 
4969 	g_test_add_func ("/media/category", test_media_category);
4970 	g_test_add_func ("/media/category/escaping", test_media_category_escaping);
4971 	g_test_add_func ("/media/content", test_media_content);
4972 	g_test_add_func ("/media/credit", test_media_credit);
4973 	/* g_test_add_func ("/media/group", test_media_group); */
4974 	g_test_add_func ("/media/thumbnail", test_media_thumbnail);
4975 	/*g_test_add_data_func ("/media/thumbnail/parse_time", "", test_media_thumbnail_parse_time);
4976 	g_test_add_data_func ("/media/thumbnail/parse_time", "de_DE", test_media_thumbnail_parse_time);*/
4977 
4978 	g_test_add_func ("/gcontact/calendar", test_gcontact_calendar);
4979 	g_test_add_func ("/gcontact/calendar/error_handling", test_gcontact_calendar_error_handling);
4980 	g_test_add_func ("/gcontact/calendar/escaping", test_gcontact_calendar_escaping);
4981 	g_test_add_func ("/gcontact/event", test_gcontact_event);
4982 	g_test_add_func ("/gcontact/event/error_handling", test_gcontact_event_error_handling);
4983 	g_test_add_func ("/gcontact/event/escaping", test_gcontact_event_escaping);
4984 	g_test_add_func ("/gcontact/external_id", test_gcontact_external_id);
4985 	g_test_add_func ("/gcontact/external_id/error_handling", test_gcontact_external_id_error_handling);
4986 	g_test_add_func ("/gcontact/external_id/escaping", test_gcontact_external_id_escaping);
4987 	g_test_add_func ("/gcontact/jot", test_gcontact_jot);
4988 	g_test_add_func ("/gcontact/jot/error_handling", test_gcontact_jot_error_handling);
4989 	g_test_add_func ("/gcontact/jot/escaping", test_gcontact_jot_escaping);
4990 	g_test_add_func ("/gcontact/language", test_gcontact_language);
4991 	g_test_add_func ("/gcontact/language/error_handling", test_gcontact_language_error_handling);
4992 	g_test_add_func ("/gcontact/language/escaping", test_gcontact_language_escaping);
4993 	g_test_add_func ("/gcontact/relation", test_gcontact_relation);
4994 	g_test_add_func ("/gcontact/relation/error_handling", test_gcontact_relation_error_handling);
4995 	g_test_add_func ("/gcontact/relation/escaping", test_gcontact_relation_escaping);
4996 	g_test_add_func ("/gcontact/website", test_gcontact_website);
4997 	g_test_add_func ("/gcontact/website/label", test_gcontact_website_label);
4998 	g_test_add_func ("/gcontact/website/error_handling", test_gcontact_website_error_handling);
4999 	g_test_add_func ("/gcontact/website/escaping", test_gcontact_website_escaping);
5000 
5001 	g_test_add_func ("/documents/property/parse_json", test_documents_property_parse_json);
5002 	g_test_add_func ("/documents/property/get_json", test_documents_property_get_json);
5003 
5004 	return g_test_run ();
5005 }
5006