geary/test/engine/api/geary-attachment-test.vala
Michael James Gratton 037af00740 Improve how attachments are saved to the db and disk.
This mostly aims to make the Geary.Attachment and ImapDB.Attachment
objects usable more generally for managing attachments, allowing
these to be instantiated once, persisted, and then reused, rather than
going through a number of representations (GMime, SQlite, Geary) and
having to be saved and re-loaded.

* src/engine/api/geary-attachment.vala (Attachment): Remove id property
  and allow both file and filesize properties to be set after instances
  are constructed. Update call sites.

* src/engine/api/geary-email.vala (Email): Remove get_attachment_by_id
  since it unused.

* src/engine/imap-db/imap-db-attachment.vala (Attachment): Chase
  Geary.Attachment API changes, move object-specific persistence code
  into methods on the actual object class itself and modernise a
  bit. Rename static methods to be a bit more terse. Update call sites
  and add unit tests.

* src/engine/imap-db/imap-db-folder.vala (Folder): Rather than saving
  attachments to the db then reloading them to add them to their email
  objects, just instantiate Attachment instances once, save and then add
  them.

* src/engine/imap-db/imap-db-gc.vala (GC): Replace custom SQL with
  existing accessor for listing attachments.

* src/engine/util/util-stream.vala (MimeOutputStream): New adaptor class
  for GMime streams to GIO output streams.
2018-05-10 13:53:24 +10:00

243 lines
8.1 KiB
Vala

/*
* Copyright 2016 Michael Gratton <mike@vee.net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
*/
// Defined by CMake build script.
extern const string _SOURCE_ROOT_DIR;
class Geary.AttachmentTest : TestCase {
private const string CONTENT_TYPE = "image/png";
private const string CONTENT_ID = "test-content-id";
private const string CONTENT_DESC = "Mea navis volitans anguillis plena est";
private const string FILE_PATH = "icons/hicolor/16x16/apps/org.gnome.Geary.png";
private Mime.ContentType? content_type;
private Mime.ContentType? default_type;
private Mime.ContentDisposition? content_disposition;
private File? file;
private class TestAttachment : Attachment {
// A test article
internal TestAttachment(Mime.ContentType content_type,
string? content_id,
string? content_description,
Mime.ContentDisposition content_disposition,
string? content_filename,
GLib.File file) {
base(content_type, content_id, content_description,
content_disposition, content_filename);
set_file_info(file, 742);
}
}
public AttachmentTest() {
base("Geary.AttachmentTest");
add_test("get_safe_file_name_with_content_name",
get_safe_file_name_with_content_name);
add_test("get_safe_file_name_with_bad_content_name",
get_safe_file_name_with_bad_content_name);
add_test("get_safe_file_name_with_bad_file_name",
get_safe_file_name_with_bad_file_name);
add_test("get_safe_file_name_with_alt_file_name",
get_safe_file_name_with_alt_file_name);
add_test("get_safe_file_name_with_no_content_name",
get_safe_file_name_with_no_content_name);
add_test("get_safe_file_name_with_no_content_name_or_id",
get_safe_file_name_with_no_content_name_or_id);
add_test("get_safe_file_name_with_default_content_type",
get_safe_file_name_with_default_content_type);
add_test("get_safe_file_name_with_default_content_type_bad_file_name",
get_safe_file_name_with_default_content_type_bad_file_name);
add_test("get_safe_file_name_with_unknown_content_type",
get_safe_file_name_with_unknown_content_type);
}
public override void set_up() {
try {
this.content_type = Mime.ContentType.deserialize(CONTENT_TYPE);
this.default_type = Mime.ContentType.deserialize(Mime.ContentType.DEFAULT_CONTENT_TYPE);
this.content_disposition = new Mime.ContentDisposition("attachment", null);
File source = File.new_for_path(_SOURCE_ROOT_DIR);
this.file = source.get_child(FILE_PATH);
} catch (Error err) {
assert_not_reached();
}
}
public void get_safe_file_name_with_content_name() throws Error {
const string TEST_FILENAME = "test-filename.png";
Attachment test = new TestAttachment(
this.content_type,
CONTENT_ID,
CONTENT_DESC,
content_disposition,
TEST_FILENAME,
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
assert(test.get_safe_file_name.end(async_result()) == TEST_FILENAME);
}
public void get_safe_file_name_with_bad_content_name() throws Error {
const string TEST_FILENAME = "test-filename.jpg";
const string RESULT_FILENAME = "test-filename.jpg.png";
Attachment test = new TestAttachment(
this.content_type,
CONTENT_ID,
CONTENT_DESC,
content_disposition,
TEST_FILENAME,
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
assert(test.get_safe_file_name.end(async_result()) == RESULT_FILENAME);
}
public void get_safe_file_name_with_bad_file_name() throws Error {
const string TEST_FILENAME = "test-filename";
const string RESULT_FILENAME = "test-filename.png";
Attachment test = new TestAttachment(
this.content_type,
CONTENT_ID,
CONTENT_DESC,
content_disposition,
TEST_FILENAME,
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
assert(test.get_safe_file_name.end(async_result()) == RESULT_FILENAME);
}
public void get_safe_file_name_with_no_content_name() throws Error {
const string RESULT_FILENAME = CONTENT_ID + ".png";
Attachment test = new TestAttachment(
this.content_type,
CONTENT_ID,
CONTENT_DESC,
content_disposition,
null,
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
assert(test.get_safe_file_name.end(async_result()) == RESULT_FILENAME);
}
public void get_safe_file_name_with_no_content_name_or_id() throws Error {
const string RESULT_FILENAME = "attachment.png";
Attachment test = new TestAttachment(
this.content_type,
null,
CONTENT_DESC,
content_disposition,
null,
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
assert(test.get_safe_file_name.end(async_result()) == RESULT_FILENAME);
}
public void get_safe_file_name_with_alt_file_name() throws Error {
const string ALT_TEXT = "some text";
const string RESULT_FILENAME = "some text.png";
Attachment test = new TestAttachment(
this.content_type,
null,
CONTENT_DESC,
content_disposition,
null,
this.file
);
test.get_safe_file_name.begin(ALT_TEXT, (obj, ret) => {
async_complete(ret);
});
assert(test.get_safe_file_name.end(async_result()) == RESULT_FILENAME);
}
public void get_safe_file_name_with_default_content_type() throws Error {
const string TEST_FILENAME = "test-filename.png";
Attachment test = new TestAttachment(
this.default_type,
CONTENT_ID,
CONTENT_DESC,
content_disposition,
TEST_FILENAME,
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
assert(test.get_safe_file_name.end(async_result()) == TEST_FILENAME);
}
public void get_safe_file_name_with_default_content_type_bad_file_name()
throws Error {
const string TEST_FILENAME = "test-filename.jpg";
const string RESULT_FILENAME = "test-filename.jpg.png";
Attachment test = new TestAttachment(
this.default_type,
CONTENT_ID,
CONTENT_DESC,
content_disposition,
TEST_FILENAME,
this.file
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
assert(test.get_safe_file_name.end(async_result()) == RESULT_FILENAME);
}
public void get_safe_file_name_with_unknown_content_type()
throws Error {
const string TEST_FILENAME = "test-filename.unlikely";
Attachment test = new TestAttachment(
this.default_type,
CONTENT_ID,
CONTENT_DESC,
content_disposition,
TEST_FILENAME,
File.new_for_path(TEST_FILENAME)
);
test.get_safe_file_name.begin(null, (obj, ret) => {
async_complete(ret);
});
assert_string(TEST_FILENAME, test.get_safe_file_name.end(async_result()));
}
}