Add unit tests for Geary.RFC822.Message body content, fix a few issues.
* src/engine/rfc822/rfc822-message.vala (Message): Fix has_plain_body(), handle the case where displayed MIME entities (as opposed to attached ones) with no Content-Type default to US-ASCII, per the RFC. * test/engine/rfc822-message-test.vala (MessageTest): Add tests for testing and accessing body content as both plain text and HTML. Use GResources for accessing test message bodies rather than extremely long const strings.
This commit is contained in:
parent
a2a95686b4
commit
bfe665d1a0
8 changed files with 248 additions and 62 deletions
|
|
@ -471,7 +471,7 @@ public class Geary.RFC822.Message : BaseObject {
|
|||
* Determines if the message has one or plain text display parts.
|
||||
*/
|
||||
public bool has_plain_body() {
|
||||
return has_body_parts(message.get_mime_part(), "text");
|
||||
return has_body_parts(message.get_mime_part(), "plain");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -486,10 +486,16 @@ public class Geary.RFC822.Message : BaseObject {
|
|||
*/
|
||||
private bool has_body_parts(GMime.Object node, string text_subtype) {
|
||||
bool has_part = false;
|
||||
Mime.ContentType? this_content_type = null;
|
||||
if (node.get_content_type() != null)
|
||||
this_content_type =
|
||||
new Mime.ContentType.from_gmime(node.get_content_type());
|
||||
|
||||
// RFC 2045 Section 5.2 allows us to assume
|
||||
// text/plain US-ASCII if no content type is
|
||||
// otherwise specified.
|
||||
Mime.ContentType this_content_type = Mime.ContentType.DISPLAY_DEFAULT;
|
||||
if (node.get_content_type() != null) {
|
||||
this_content_type = new Mime.ContentType.from_gmime(
|
||||
node.get_content_type()
|
||||
);
|
||||
}
|
||||
|
||||
GMime.Multipart? multipart = node as GMime.Multipart;
|
||||
if (multipart != null) {
|
||||
|
|
@ -508,8 +514,7 @@ public class Geary.RFC822.Message : BaseObject {
|
|||
|
||||
if (disposition == null ||
|
||||
disposition.disposition_type != Mime.DispositionType.ATTACHMENT) {
|
||||
if (this_content_type != null &&
|
||||
this_content_type.has_media_type("text") &&
|
||||
if (this_content_type.has_media_type("text") &&
|
||||
this_content_type.has_media_subtype(text_subtype)) {
|
||||
has_part = true;
|
||||
}
|
||||
|
|
@ -537,10 +542,15 @@ public class Geary.RFC822.Message : BaseObject {
|
|||
*/
|
||||
private bool construct_body_from_mime_parts(GMime.Object node, Mime.MultipartSubtype container_subtype,
|
||||
string text_subtype, bool to_html, InlinePartReplacer? replacer, ref string? body) throws RFC822Error {
|
||||
Mime.ContentType? this_content_type = null;
|
||||
if (node.get_content_type() != null)
|
||||
this_content_type = new Mime.ContentType.from_gmime(node.get_content_type());
|
||||
|
||||
// RFC 2045 Section 5.2 allows us to assume text/plain
|
||||
// US-ASCII if no content type is otherwise specified.
|
||||
Mime.ContentType this_content_type = Mime.ContentType.DISPLAY_DEFAULT;
|
||||
if (node.get_content_type() != null) {
|
||||
this_content_type = new Mime.ContentType.from_gmime(
|
||||
node.get_content_type()
|
||||
);
|
||||
}
|
||||
|
||||
// If this is a multipart, call ourselves recursively on the children
|
||||
GMime.Multipart? multipart = node as GMime.Multipart;
|
||||
if (multipart != null) {
|
||||
|
|
|
|||
36
test/data/basic-multipart-alternative.eml
Normal file
36
test/data/basic-multipart-alternative.eml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
From: Alice <alice@example.net>
|
||||
Sender: Bob <bob@example.net>
|
||||
To: Charlie <charlie@example.net>
|
||||
CC: Dave <dave@example.net>
|
||||
BCC: Eve <eve@example.net>
|
||||
Reply-To: \"Alice: Personal Account\" <alice@example.org>
|
||||
Subject: Re: Basic text/html message
|
||||
Date: Fri, 21 Nov 1997 10:01:10 -0600
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/alternative; boundary="=-NJextDaQ1tE2ZGhW9Wm0"
|
||||
Message-ID: <3456@example.net>
|
||||
In-Reply-To: <1234@local.machine.example>
|
||||
References: <1234@local.machine.example>
|
||||
X-Mailer: Geary Test Suite 1.0
|
||||
|
||||
--=-NJextDaQ1tE2ZGhW9Wm0
|
||||
Content-Type: text/plain; charset=UTF-8; format=flowed
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
This is the first line.
|
||||
|
||||
This is the second line.
|
||||
|
||||
=
|
||||
|
||||
--=-NJextDaQ1tE2ZGhW9Wm0
|
||||
Content-Type: text/html; charset=UTF-8
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
<P>This is the first line.
|
||||
|
||||
<P>This is the second line.
|
||||
|
||||
=
|
||||
|
||||
--=-NJextDaQ1tE2ZGhW9Wm0--
|
||||
18
test/data/basic-text-html.eml
Normal file
18
test/data/basic-text-html.eml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
From: Alice <alice@example.net>
|
||||
Sender: Bob <bob@example.net>
|
||||
To: Charlie <charlie@example.net>
|
||||
CC: Dave <dave@example.net>
|
||||
BCC: Eve <eve@example.net>
|
||||
Reply-To: \"Alice: Personal Account\" <alice@example.org>
|
||||
Subject: Re: Basic text/html message
|
||||
Date: Fri, 21 Nov 1997 10:01:10 -0600
|
||||
Content-Type: text/html; charset=UTF-8
|
||||
Message-ID: <3456@example.net>
|
||||
In-Reply-To: <1234@local.machine.example>
|
||||
References: <1234@local.machine.example>
|
||||
X-Mailer: Geary Test Suite 1.0
|
||||
|
||||
<P>This is the first line.
|
||||
|
||||
<P>This is the second line.
|
||||
|
||||
17
test/data/basic-text-plain.eml
Normal file
17
test/data/basic-text-plain.eml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
From: Alice <alice@example.net>
|
||||
Sender: Bob <bob@example.net>
|
||||
To: Charlie <charlie@example.net>
|
||||
CC: Dave <dave@example.net>
|
||||
BCC: Eve <eve@example.net>
|
||||
Reply-To: "Alice: Personal Account" <alice@example.org>
|
||||
Subject: Re: Basic text/plain message
|
||||
Date: Fri, 21 Nov 1997 10:01:10 -0600
|
||||
Message-ID: <3456@example.net>
|
||||
In-Reply-To: <1234@local.machine.example>
|
||||
References: <1234@local.machine.example>
|
||||
X-Mailer: Geary Test Suite 1.0
|
||||
|
||||
This is the first line.
|
||||
|
||||
This is the second line.
|
||||
|
||||
3
test/data/meson.build
Normal file
3
test/data/meson.build
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
geary_test_engine_resources = gnome.compile_resources('org.gnome.GearyTest',
|
||||
files('org.gnome.GearyTest.gresource.xml'),
|
||||
)
|
||||
8
test/data/org.gnome.GearyTest.gresource.xml
Normal file
8
test/data/org.gnome.GearyTest.gresource.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<gresources>
|
||||
<gresource prefix="/org/gnome/GearyTest">
|
||||
<file>basic-text-plain.eml</file>
|
||||
<file>basic-text-html.eml</file>
|
||||
<file>basic-multipart-alternative.eml</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
|
@ -7,29 +7,57 @@
|
|||
|
||||
class Geary.RFC822.MessageTest : TestCase {
|
||||
|
||||
private const string RESOURCE_URI = "resource:///org/gnome/GearyTest";
|
||||
|
||||
private const string BASIC_TEXT_PLAIN = "basic-text-plain.eml";
|
||||
private const string BASIC_TEXT_HTML = "basic-text-html.eml";
|
||||
private const string BASIC_MULTIPART_ALTERNATIVE =
|
||||
"basic-multipart-alternative.eml";
|
||||
|
||||
private const string HTML_CONVERSION_TEMPLATE =
|
||||
"<div class=\"plaintext\" style=\"white-space: pre-wrap;\">%s</div>";
|
||||
|
||||
private const string BASIC_PLAIN_BODY = """This is the first line.
|
||||
|
||||
This is the second line.
|
||||
|
||||
""";
|
||||
|
||||
private const string BASIC_HTML_BODY = """<P>This is the first line.
|
||||
|
||||
<P>This is the second line.
|
||||
|
||||
""";
|
||||
|
||||
public MessageTest() {
|
||||
base("Geary.RFC822.MessageTest");
|
||||
add_test("basic_message_from_buffer", basic_message_from_buffer);
|
||||
add_test("encoded_recipient", encoded_recipient);
|
||||
add_test("duplicate_mailbox", duplicate_mailbox);
|
||||
add_test("duplicate_message_id", duplicate_message_id);
|
||||
add_test("text_plain_as_plain", text_plain_as_plain);
|
||||
add_test("text_plain_as_html", text_plain_as_html);
|
||||
add_test("text_html_as_html", text_html_as_html);
|
||||
add_test("text_html_as_plain", text_html_as_plain);
|
||||
add_test("multipart_alternative_as_plain",
|
||||
multipart_alternative_as_plain);
|
||||
add_test("multipart_alternative_as_converted_html",
|
||||
multipart_alternative_as_converted_html);
|
||||
add_test("multipart_alternative_as_html",
|
||||
multipart_alternative_as_html);
|
||||
add_test("get_preview", get_preview);
|
||||
}
|
||||
|
||||
public void basic_message_from_buffer() throws Error {
|
||||
Message? basic = null;
|
||||
try {
|
||||
basic = string_to_message(BASIC_MESSAGE);
|
||||
} catch (Error err) {
|
||||
assert_no_error(err);
|
||||
}
|
||||
assert_data(basic.subject, "Re: Saying Hello");
|
||||
assert_addresses(basic.from, "Mary Smith <mary@example.net>");
|
||||
assert_address(basic.sender, "Mary Smith Sender <mary@example.net>");
|
||||
assert_addresses(basic.reply_to, "\"Mary Smith: Personal Account\" <smith@home.example>");
|
||||
assert_addresses(basic.to, "John Doe <jdoe@machine.example>");
|
||||
assert_addresses(basic.cc, "John Doe CC <jdoe@machine.example>");
|
||||
assert_addresses(basic.bcc, "John Doe BCC <jdoe@machine.example>");
|
||||
Message basic = resource_to_message(BASIC_TEXT_PLAIN);
|
||||
|
||||
assert_data(basic.subject, "Re: Basic text/plain message");
|
||||
assert_addresses(basic.from, "Alice <alice@example.net>");
|
||||
assert_address(basic.sender, "Bob <bob@example.net>");
|
||||
assert_addresses(basic.reply_to, "\"Alice: Personal Account\" <alice@example.org>");
|
||||
assert_addresses(basic.to, "Charlie <charlie@example.net>");
|
||||
assert_addresses(basic.cc, "Dave <dave@example.net>");
|
||||
assert_addresses(basic.bcc, "Eve <eve@example.net>");
|
||||
//assert_data(basic.message_id, "<3456@example.net>");
|
||||
assert_message_id_list(basic.in_reply_to, "<1234@local.machine.example>");
|
||||
assert_message_id_list(basic.references, "<1234@local.machine.example>");
|
||||
|
|
@ -38,24 +66,14 @@ class Geary.RFC822.MessageTest : TestCase {
|
|||
}
|
||||
|
||||
public void encoded_recipient() throws Error {
|
||||
Message? enc = null;
|
||||
try {
|
||||
enc = string_to_message(ENCODED_TO);
|
||||
} catch (Error err) {
|
||||
assert_no_error(err);
|
||||
}
|
||||
Message enc = string_to_message(ENCODED_TO);
|
||||
|
||||
// Courtesy Mailsploit https://www.mailsploit.com
|
||||
assert(enc.to[0].name == "potus@whitehouse.gov <test>");
|
||||
}
|
||||
|
||||
public void duplicate_mailbox() throws Error {
|
||||
Message? dup = null;
|
||||
try {
|
||||
dup = string_to_message(DUPLICATE_TO);
|
||||
} catch (Error err) {
|
||||
assert_no_error(err);
|
||||
}
|
||||
Message dup = string_to_message(DUPLICATE_TO);
|
||||
|
||||
assert(dup.to.size == 2);
|
||||
assert_addresses(
|
||||
|
|
@ -64,12 +82,7 @@ class Geary.RFC822.MessageTest : TestCase {
|
|||
}
|
||||
|
||||
public void duplicate_message_id() throws Error {
|
||||
Message? dup = null;
|
||||
try {
|
||||
dup = string_to_message(DUPLICATE_REFERENCES);
|
||||
} catch (Error err) {
|
||||
assert_no_error(err);
|
||||
}
|
||||
Message dup = string_to_message(DUPLICATE_REFERENCES);
|
||||
|
||||
assert(dup.references.list.size == 2);
|
||||
assert_message_id_list(
|
||||
|
|
@ -77,13 +90,84 @@ class Geary.RFC822.MessageTest : TestCase {
|
|||
);
|
||||
}
|
||||
|
||||
public void text_plain_as_plain() throws Error {
|
||||
Message test = resource_to_message(BASIC_TEXT_PLAIN);
|
||||
|
||||
assert_true(test.has_plain_body(), "Expected plain body");
|
||||
assert_false(test.has_html_body(), "Expected non-html body");
|
||||
assert_string(BASIC_PLAIN_BODY, test.get_plain_body(false, null));
|
||||
}
|
||||
|
||||
public void text_plain_as_html() throws Error {
|
||||
Message test = resource_to_message(BASIC_TEXT_PLAIN);
|
||||
|
||||
assert_true(test.has_plain_body(), "Expected plain body");
|
||||
assert_false(test.has_html_body(), "Expected non-html body");
|
||||
assert_string(
|
||||
HTML_CONVERSION_TEMPLATE.printf(BASIC_PLAIN_BODY),
|
||||
test.get_plain_body(true, null)
|
||||
);
|
||||
}
|
||||
|
||||
public void text_html_as_html() throws Error {
|
||||
Message test = resource_to_message(BASIC_TEXT_HTML);
|
||||
|
||||
assert_true(test.has_html_body(), "Expected html body");
|
||||
assert_false(test.has_plain_body(), "Expected non-plain body");
|
||||
assert_string(BASIC_HTML_BODY, test.get_html_body(null));
|
||||
}
|
||||
|
||||
public void text_html_as_plain() throws Error {
|
||||
Message test = resource_to_message(BASIC_TEXT_HTML);
|
||||
|
||||
assert_true(test.has_html_body(), "Expected html body");
|
||||
assert_false(test.has_plain_body(), "Expected non-plain body");
|
||||
assert_string(BASIC_HTML_BODY, test.get_html_body(null));
|
||||
}
|
||||
|
||||
public void multipart_alternative_as_plain() throws Error {
|
||||
Message test = resource_to_message(BASIC_MULTIPART_ALTERNATIVE);
|
||||
|
||||
assert_true(test.has_plain_body(), "Expected plain body");
|
||||
assert_true(test.has_html_body(), "Expected html body");
|
||||
assert_string(BASIC_PLAIN_BODY, test.get_plain_body(false, null));
|
||||
}
|
||||
|
||||
public void multipart_alternative_as_converted_html() throws Error {
|
||||
Message test = resource_to_message(BASIC_MULTIPART_ALTERNATIVE);
|
||||
|
||||
assert_true(test.has_plain_body(), "Expected plain body");
|
||||
assert_true(test.has_html_body(), "Expected html body");
|
||||
assert_string(
|
||||
HTML_CONVERSION_TEMPLATE.printf(BASIC_PLAIN_BODY),
|
||||
test.get_plain_body(true, null)
|
||||
);
|
||||
}
|
||||
|
||||
public void multipart_alternative_as_html() throws Error {
|
||||
Message test = resource_to_message(BASIC_MULTIPART_ALTERNATIVE);
|
||||
|
||||
assert_true(test.has_plain_body(), "Expected plain body");
|
||||
assert_true(test.has_html_body(), "Expected html body");
|
||||
assert_string(BASIC_HTML_BODY, test.get_html_body(null));
|
||||
}
|
||||
|
||||
public void get_preview() throws Error {
|
||||
try {
|
||||
Message multipart_signed = string_to_message(MULTIPART_SIGNED_MESSAGE_TEXT);
|
||||
assert(multipart_signed.get_preview() == MULTIPART_SIGNED_MESSAGE_PREVIEW);
|
||||
} catch (Error err) {
|
||||
assert_no_error(err);
|
||||
}
|
||||
Message multipart_signed = string_to_message(MULTIPART_SIGNED_MESSAGE_TEXT);
|
||||
|
||||
assert(multipart_signed.get_preview() == MULTIPART_SIGNED_MESSAGE_PREVIEW);
|
||||
}
|
||||
|
||||
private Message resource_to_message(string path) throws Error {
|
||||
GLib.File resource =
|
||||
GLib.File.new_for_uri(RESOURCE_URI).resolve_relative_path(path);
|
||||
|
||||
uint8[] contents;
|
||||
resource.load_contents(null, out contents, null);
|
||||
|
||||
return new Message.from_buffer(
|
||||
new Geary.Memory.ByteBuffer(contents, contents.length)
|
||||
);
|
||||
}
|
||||
|
||||
private Message string_to_message(string message_text) throws Error {
|
||||
|
|
@ -92,28 +176,34 @@ class Geary.RFC822.MessageTest : TestCase {
|
|||
);
|
||||
}
|
||||
|
||||
private void assert_data(Geary.MessageData.AbstractMessageData? data, string expected) {
|
||||
assert(data != null);
|
||||
assert(data.to_string() == expected);
|
||||
private void assert_data(Geary.MessageData.AbstractMessageData? actual,
|
||||
string expected)
|
||||
throws Error {
|
||||
assert_non_null(actual, expected);
|
||||
assert_string(expected, actual.to_string());
|
||||
}
|
||||
|
||||
private void assert_address(Geary.RFC822.MailboxAddress? address, string expected) {
|
||||
assert(address != null);
|
||||
assert(address.to_rfc822_string() == expected);
|
||||
private void assert_address(Geary.RFC822.MailboxAddress? address,
|
||||
string expected)
|
||||
throws Error {
|
||||
assert_non_null(address, expected);
|
||||
assert_string(expected, address.to_rfc822_string());
|
||||
}
|
||||
|
||||
private void assert_addresses(Geary.RFC822.MailboxAddresses? addresses, string expected) {
|
||||
assert(addresses != null);
|
||||
assert(addresses.to_rfc822_string() == expected);
|
||||
private void assert_addresses(Geary.RFC822.MailboxAddresses? addresses,
|
||||
string expected)
|
||||
throws Error {
|
||||
assert_non_null(addresses, expected);
|
||||
assert_string(expected, addresses.to_rfc822_string());
|
||||
}
|
||||
|
||||
private void assert_message_id_list(Geary.RFC822.MessageIDList? ids, string expected) {
|
||||
assert(ids != null);
|
||||
private void assert_message_id_list(Geary.RFC822.MessageIDList? ids,
|
||||
string expected)
|
||||
throws Error {
|
||||
assert_non_null(ids, expected);
|
||||
assert(ids.to_rfc822_string() == expected);
|
||||
}
|
||||
|
||||
private static string BASIC_MESSAGE = "From: Mary Smith <mary@example.net>\r\nSender: Mary Smith Sender <mary@example.net>\r\nTo: John Doe <jdoe@machine.example>\r\nCC: John Doe CC <jdoe@machine.example>\r\nBCC: John Doe BCC <jdoe@machine.example>\r\nReply-To: \"Mary Smith: Personal Account\" <smith@home.example>\r\nSubject: Re: Saying Hello\r\nDate: Fri, 21 Nov 1997 10:01:10 -0600\r\nMessage-ID: <3456@example.net>\r\nIn-Reply-To: <1234@local.machine.example>\r\nReferences: <1234@local.machine.example>\r\nX-Mailer: Geary Test Suite 1.0\r\n\r\nThis is a reply to your hello.\r\n\r\n";
|
||||
|
||||
// Courtesy Mailsploit https://www.mailsploit.com
|
||||
private static string ENCODED_TO = "From: Mary Smith <mary@example.net>\r\nTo: =?utf-8?b?cG90dXNAd2hpdGVob3VzZS5nb3YiIDx0ZXN0Pg==?= <jdoe@machine.example>\r\nSubject: Re: Saying Hello\r\nDate: Fri, 21 Nov 1997 10:01:10 -0600\r\n\r\nThis is a reply to your hello.\r\n\r\n";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
subdir('data')
|
||||
|
||||
geary_test_lib_sources = [
|
||||
'mock-object.vala',
|
||||
'test-case.vala',
|
||||
|
|
@ -41,7 +43,9 @@ geary_test_engine_sources = [
|
|||
'engine/util-inet-test.vala',
|
||||
'engine/util-js-test.vala',
|
||||
'engine/util-string-test.vala',
|
||||
'engine/util-timeout-manager-test.vala'
|
||||
'engine/util-timeout-manager-test.vala',
|
||||
|
||||
geary_test_engine_resources
|
||||
]
|
||||
|
||||
geary_test_client_sources = [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue