[geary/wip/integration-tests: 3/3] Add initial integration test famework and IMAP client session tests



commit 416ee71571dd704d470a70aadc6f59c95f3d6f46
Author: Michael Gratton <mike vee net>
Date:   Sun Mar 31 01:42:08 2019 +1100

    Add initial integration test famework and IMAP client session tests

 test/README.md                            |  53 +++++++++++++++
 test/integration/imap/client-session.vala |  99 +++++++++++++++++++++++++++
 test/meson.build                          |  27 +++++++-
 test/test-integration.vala                | 107 ++++++++++++++++++++++++++++++
 4 files changed, 283 insertions(+), 3 deletions(-)
---
diff --git a/test/README.md b/test/README.md
new file mode 100644
index 00000000..2f634f39
--- /dev/null
+++ b/test/README.md
@@ -0,0 +1,53 @@
+
+Automated Test Infrastructure
+=============================
+
+Geary currently supports three types of automated tests:
+
+ * Engine unit tests
+ * Client (GTK and JavaScript) unit tests
+ * Server integration tests
+
+Unit tests
+----------
+
+Unit tests test individual functions, in general avoid doing any I/O
+so they are fast, and can be run automatically.
+
+The engine and client unit tests are hooked up to the Meson build, so
+you can use Meson's test infrastructure to build and run them. These
+are run automatically as part of the Gitlab CI process and if you use
+the development Makefile, you can execute them locally by simply
+calling:
+
+    make test
+
+The engine tests can be run headless (i.e. without an X11 or Wayland
+session), but the client tests require a functioning display since
+they execute GTK code.
+
+Integration tests
+-----------------
+
+Integration tests run Geary's network code against actual servers, to
+ensure that the code also works in the real world.
+
+The integration tests are built by default, but not currently hooked
+up to Meson and are not automatically run by Gitlab CI, since they
+require multiple working servers, network connection to the servers,
+and login credentials.
+
+You can run them manually however against any server you have a test
+account on, using the following form:
+
+    build/test/test-integration PROTOCOL PROVIDER [HOSTNAME] LOGIN PASSWORD
+
+For example, to test against GMail's IMAP service:
+
+    build/test/test-integration imap gmail test gmail com p455w04d
+
+If `PROVIDER` is `other`, then `HOSTNAME` is required.
+
+The easiest way to test against a number of different servers at the
+moment is to create a test account for each, then write a shell script
+or similar to execute the tests against each in turn.
diff --git a/test/integration/imap/client-session.vala b/test/integration/imap/client-session.vala
new file mode 100644
index 00000000..6cf5ec2e
--- /dev/null
+++ b/test/integration/imap/client-session.vala
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019 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.
+ */
+
+class Integration.Imap.ClientSession : TestCase {
+
+
+    private Configuration config;
+    private Geary.Imap.ClientSession? session;
+
+
+    public ClientSession(Configuration config) {
+        base("Integration.Imap.ClientSession");
+        this.config = config;
+        add_test("session_connect", session_connect);
+
+        add_test("login_password_invalid", login_password_invalid);
+        if (config.provider == GMAIL ||
+            config.provider == OUTLOOK) {
+            add_test("login_oauth2_invalid", login_oauth2_invalid);
+        }
+
+        add_test("initiate_session", initiate_session);
+    }
+
+    public override void set_up() {
+        this.session = new Geary.Imap.ClientSession(
+            this.config.target
+        );
+    }
+
+    public override void tear_down() throws GLib.Error {
+        if (this.session.get_protocol_state(null) != UNCONNECTED) {
+            this.session.disconnect_async.begin(null, async_complete_full);
+            this.session.disconnect_async.end(async_result());
+        }
+        this.session = null;
+    }
+
+    public void session_connect() throws GLib.Error {
+        this.session.connect_async.begin(null, async_complete_full);
+        this.session.connect_async.end(async_result());
+
+        this.session.disconnect_async.begin(null, async_complete_full);
+        this.session.disconnect_async.end(async_result());
+    }
+
+    public void login_password_invalid() throws GLib.Error {
+        do_connect();
+
+        Geary.Credentials password_creds = new Geary.Credentials(
+            PASSWORD, "automated-integration-test", "password"
+        );
+        this.session.login_async.begin(
+            password_creds, null, async_complete_full
+        );
+        try {
+            this.session.login_async.end(async_result());
+            assert_not_reached();
+        } catch (Geary.ImapError.UNAUTHENTICATED err) {
+            // All good
+        }
+    }
+
+    public void login_oauth2_invalid() throws GLib.Error {
+        do_connect();
+
+        Geary.Credentials oauth2_creds = new Geary.Credentials(
+            OAUTH2, "automated-integration-test", "password"
+        );
+        this.session.login_async.begin(
+            oauth2_creds, null, async_complete_full
+        );
+        try {
+            this.session.login_async.end(async_result());
+            assert_not_reached();
+        } catch (Geary.ImapError.UNAUTHENTICATED err) {
+            // All good
+        }
+    }
+
+    public void initiate_session() throws GLib.Error {
+        do_connect();
+
+        this.session.initiate_session_async.begin(
+            this.config.credentials, null, async_complete_full
+        );
+        this.session.initiate_session_async.end(async_result());
+    }
+
+    private void do_connect() throws GLib.Error {
+        this.session.connect_async.begin(null, async_complete_full);
+        this.session.connect_async.end(async_result());
+    }
+
+}
diff --git a/test/meson.build b/test/meson.build
index ab3ea78c..ae3a2b9d 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -87,6 +87,12 @@ geary_test_client_sources = [
   geary_resources
 ]
 
+geary_test_integration_sources = [
+  'test-integration.vala',
+
+  'integration/imap/client-session.vala',
+]
+
 geary_test_lib_dependencies = [
   gee,
   gio,
@@ -103,7 +109,7 @@ geary_test_client_dependencies = [
 ]
 geary_test_client_dependencies += geary_client_dependencies
 
-geary_test_lib = static_library('geary-test-lib',
+geary_test_lib = static_library('test-lib',
   geary_test_lib_sources,
   dependencies: geary_test_lib_dependencies,
   include_directories: config_h_dir,
@@ -111,7 +117,7 @@ geary_test_lib = static_library('geary-test-lib',
   c_args: geary_c_options,
 )
 
-geary_test_engine_bin = executable('geary-test-engine',
+geary_test_engine_bin = executable('test-engine',
   geary_test_engine_sources,
   link_with: geary_test_lib,
   dependencies: geary_test_engine_dependencies,
@@ -120,7 +126,7 @@ geary_test_engine_bin = executable('geary-test-engine',
   c_args: geary_c_options,
 )
 
-geary_test_client_bin = executable('geary-test-client',
+geary_test_client_bin = executable('test-client',
   geary_test_client_sources,
   dependencies: geary_test_client_dependencies,
   link_with: geary_test_lib,
@@ -129,5 +135,20 @@ geary_test_client_bin = executable('geary-test-client',
   c_args: geary_c_options,
 )
 
+geary_test_client_bin = executable('test-integration',
+  geary_test_integration_sources,
+  dependencies: [
+    geary_engine_dep,
+    gee,
+    gio,
+    gmime,
+    webkit2gtk,
+  ],
+  link_with: geary_test_lib,
+  include_directories: config_h_dir,
+  vala_args: geary_vala_options,
+  c_args: geary_c_options,
+)
+
 test('engine-tests', geary_test_engine_bin)
 test('client-tests', geary_test_client_bin)
diff --git a/test/test-integration.vala b/test/test-integration.vala
new file mode 100644
index 00000000..8204275f
--- /dev/null
+++ b/test/test-integration.vala
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2019 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.
+ */
+
+
+private const int TIMEOUT = 5;
+
+
+public struct Integration.Configuration {
+
+    Geary.Protocol type;
+    Geary.ServiceProvider provider;
+    Geary.ServiceInformation service;
+    Geary.Endpoint target;
+    Geary.Credentials credentials;
+
+}
+
+
+int main(string[] args) {
+    /*
+     * Initialise all the things.
+     */
+
+    Test.init(ref args);
+
+    Geary.RFC822.init();
+    Geary.HTML.init();
+    Geary.Logging.init();
+    Geary.Logging.log_to(stderr);
+    GLib.Log.set_default_handler(Geary.Logging.default_handler);
+
+    Integration.Configuration config = load_config(args);
+
+    /*
+     * Hook up all tests into appropriate suites
+     */
+
+    TestSuite integration = new TestSuite("integration");
+
+    switch (config.type) {
+    case IMAP:
+        integration.add_suite(
+            new Integration.Imap.ClientSession(config).get_suite()
+        );
+        break;
+    }
+
+    /*
+     * Run the tests
+     */
+    TestSuite root = TestSuite.get_root();
+    root.add_suite(integration);
+
+    MainLoop loop = new MainLoop();
+
+    int ret = -1;
+    Idle.add(() => {
+            ret = Test.run();
+            loop.quit();
+            return false;
+        });
+
+    loop.run();
+    return ret;
+}
+
+private Integration.Configuration load_config(string[] args) {
+    int i = 1;
+    try {
+        Geary.Protocol type = Geary.Protocol.for_value(args[i++]);
+        Geary.ServiceProvider provider = Geary.ServiceProvider.for_value(
+            args[i++]
+        );
+        Geary.ServiceInformation service = new Geary.ServiceInformation(
+            type, provider
+        );
+
+        if (provider == OTHER) {
+            service.host = args[i++];
+            service.port = service.get_default_port();
+        }
+
+        Geary.Credentials credentials = new Geary.Credentials(
+            PASSWORD, args[i++], args[i++]
+        );
+
+        provider.set_service_defaults(service);
+
+        Geary.Endpoint target = new Geary.Endpoint(
+            new NetworkAddress(service.host, service.port),
+            service.transport_security,
+            TIMEOUT
+        );
+
+        return { type, provider, service, target, credentials };
+    } catch (GLib.Error err) {
+        error(
+            "Error loading config: %s",
+            (new Geary.ErrorContext(err)).format_full_error()
+        );
+    }
+
+}
\ No newline at end of file


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]