[rygel] tests: Add RygelUserConfigTest



commit f2819cf348b965c61156c2498f94340d7e9bb500
Author: Krzesimir Nowak <krnowak openismus com>
Date:   Tue Sep 18 15:38:56 2012 +0200

    tests: Add RygelUserConfigTest
    
    For now it tests configuration loading depending on whether local or
    system configuration files exist, and monitoring of configuration
    files.

 tests/Makefile.am                 |   14 +
 tests/rygel-configuration.vala    |    1 +
 tests/rygel-user-config-test.vala |  697 +++++++++++++++++++++++++++++++++++++
 tests/rygel-user-config.vala      |    1 +
 4 files changed, 713 insertions(+), 0 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 7ee2aa7..8a0b098 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -43,6 +43,7 @@ check_PROGRAMS = rygel-http-item-uri-test \
 		 rygel-searchable-container-test \
 		 rygel-item-creator-test \
 		 rygel-playbin-renderer-test \
+		 rygel-user-config-test \
 		 rygel-regression
 
 TESTS = $(check_PROGRAMS)
@@ -117,6 +118,19 @@ rygel_playbin_renderer_test_CFLAGS = \
 	-I$(top_srcdir)/src/librygel-core
 
 
+rygel_user_config_test_SOURCES = rygel-configuration.vala \
+				 rygel-user-config.vala \
+				 rygel-user-config-test.vala
+
+rygel_user_config_test_VALAFLAGS = \
+	$(AM_VALAFLAGS) \
+	--pkg rygel-build-config
+
+rygel_user_config_test_CFLAGS = \
+	$(AM_CFLAGS) \
+	-DSYS_CONFIG_DIR='"$(sysconfigdir)"'
+
+
 rygel_regression_SOURCES = \
 	rygel-regression.vala
 
diff --git a/tests/rygel-configuration.vala b/tests/rygel-configuration.vala
new file mode 120000
index 0000000..64ed5c3
--- /dev/null
+++ b/tests/rygel-configuration.vala
@@ -0,0 +1 @@
+../src/librygel-core/rygel-configuration.vala
\ No newline at end of file
diff --git a/tests/rygel-user-config-test.vala b/tests/rygel-user-config-test.vala
new file mode 100644
index 0000000..3d84e74
--- /dev/null
+++ b/tests/rygel-user-config-test.vala
@@ -0,0 +1,697 @@
+/*
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * Author: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using Gee;
+
+public class Rygel.UserConfigTest : GLib.Object {
+
+    // pitiful Vala with no typedefs...
+    public class ConfigSet : GLib.Object {
+        public HashSet<ConfigurationEntry> gee;
+
+        public ConfigSet () {
+            this.gee = new HashSet<ConfigurationEntry> ();
+        }
+    }
+
+    public class SectionMap : GLib.Object {
+        public HashMap<string, HashSet<SectionEntry> > gee;
+
+        public SectionMap () {
+            this.gee = new HashMap<string, HashSet<SectionEntry> > ();
+        }
+
+        public HashSet<SectionEntry> new_values (string section) {
+            var values = new HashSet<SectionEntry> ();
+
+            this.gee.set (section, values);
+
+            return values;
+        }
+    }
+
+    public class SettingMap : GLib.Object {
+        public HashMap<string, HashSet<string> > gee;
+
+        public SettingMap () {
+            this.gee = new HashMap<string, HashSet<string> > ();
+        }
+
+        public HashSet<string> new_values (string section) {
+            var values = new HashSet<string> ();
+
+            this.gee.set (section, values);
+
+            return values;
+        }
+    }
+
+    private class Settings : GLib.Object {
+        public string? general_title;
+        public bool? general_enabled;
+        public bool? general_upnp_enabled;
+        public string? general_iface;
+        public int? general_port;
+        public string? foo_title;
+        public bool? foo_enabled;
+        public bool? foo_setting;
+
+        private void initialize (string? general_title = null,
+                                 bool? general_enabled = null,
+                                 bool? general_upnp_enabled = null,
+                                 string? general_iface = null,
+                                 int? general_port = null,
+                                 string? foo_title = null,
+                                 bool? foo_enabled = null,
+                                 bool? foo_setting = null) {
+            this.general_title = general_title;
+            this.general_enabled = general_enabled;
+            this.general_upnp_enabled = general_upnp_enabled;
+            this.general_iface = general_iface;
+            this.general_port = general_port;
+            this.foo_title = foo_title;
+            this.foo_enabled = foo_enabled;
+            this.foo_setting = foo_setting;
+        }
+
+        public Settings (string? general_title = null,
+                         bool? general_enabled = null,
+                         bool? general_upnp_enabled = null,
+                         string? general_iface = null,
+                         int? general_port = null,
+                         string? foo_title = null,
+                         bool? foo_enabled = null,
+                         bool? foo_setting = null) {
+            this.initialize (general_title,
+                             general_enabled,
+                             general_upnp_enabled,
+                             general_iface,
+                             general_port,
+                             foo_title,
+                             foo_enabled,
+                             foo_setting);
+        }
+
+        public Settings.default () {
+            this.initialize ("General",
+                             true,
+                             true,
+                             "eth0",
+                             42,
+                             "Foo",
+                             true,
+                             true);
+        }
+    }
+
+    private abstract class SettingsAction : GLib.Object {
+        protected UserConfigTest test;
+
+        SettingsAction (UserConfigTest test) {
+            this.test = test;
+        }
+        public abstract void perform (string config);
+    }
+
+    private class SettingsDoNothing : SettingsAction {
+        public SettingsDoNothing (UserConfigTest test) {
+            base (test);
+        }
+
+        public override void perform (string config) {}
+    }
+
+    private class SettingsReplace : SettingsAction {
+        private Settings settings;
+
+        public SettingsReplace (UserConfigTest test,
+                                Settings settings) {
+            base (test);
+            this.settings = settings;
+        }
+
+        public override void perform (string config) {
+            this.test.set_config (config,
+                                  this.settings);
+        }
+    }
+
+    private class SettingsRemove : SettingsAction {
+        public SettingsRemove (UserConfigTest test) {
+            base (test);
+        }
+
+        public override void perform (string config) {
+            this.test.remove_config (config);
+        }
+    }
+
+    private class WatchData : GLib.Object {
+        public string description;
+        public SettingsAction local_action;
+        public SettingsAction system_action;
+        public ConfigSet expected_config_changes;
+        public SectionMap expected_section_changes;
+        public SettingMap expected_setting_changes;
+
+        private bool description_printed;
+
+        private void initialize (string description,
+                                 SettingsAction local_action,
+                                 SettingsAction system_action,
+                                 ConfigSet expected_config_changes,
+                                 SectionMap expected_section_changes,
+                                 SettingMap expected_setting_changes) {
+            this.description = description;
+            this.local_action = local_action;
+            this.system_action = system_action;
+            this.expected_config_changes = expected_config_changes;
+            this.expected_section_changes = expected_section_changes;
+            this.expected_setting_changes = expected_setting_changes;
+            this.description_printed = false;
+        }
+
+        public WatchData (string description,
+                          SettingsAction local_action,
+                          SettingsAction system_action,
+                          ConfigSet expected_config_changes,
+                          SectionMap expected_section_changes,
+                          SettingMap expected_setting_changes) {
+            this.initialize (description,
+                             local_action,
+                             system_action,
+                             expected_config_changes,
+                             expected_section_changes,
+                             expected_setting_changes);
+        }
+
+        public WatchData.no_changes (string description,
+                                     SettingsAction local_action,
+                                     SettingsAction system_action) {
+            this.initialize (description,
+                             local_action,
+                             system_action,
+                             new ConfigSet (),
+                             new SectionMap (),
+                             new SettingMap ());
+        }
+
+        public bool empty () {
+            return (this.expected_config_changes.gee.size == 0 &&
+                    this.expected_section_changes.gee.size == 0 &&
+                    this.expected_setting_changes.gee.size == 0);
+        }
+
+        public void prepare_setup () {
+            this.local_action.perform (LOCAL_CONFIG);
+            this.system_action.perform (SYSTEM_CONFIG);
+        }
+
+        public void print_description () {
+            if (!this.description_printed) {
+                this.description_printed = true;
+                warning ("Test case: %s.", this.description);
+            }
+        }
+
+        public void print_expectations () {
+            warning ("Expected configuration changes so far:");
+            if (this.expected_config_changes.gee.size == 0) {
+                warning ("(none)");
+            } else {
+                foreach (var entry in this.expected_config_changes.gee) {
+                    warning ("  %s", entry.to_string ());
+                }
+            }
+            warning ("Expected section changes so far:");
+            if (this.expected_section_changes.gee.size == 0) {
+                warning ("(none)");
+            } else {
+                var changes = this.expected_section_changes.gee;
+
+                foreach (var section in changes.keys) {
+                    var entries = changes.get (section);
+
+                    warning ("  %s", section);
+                    foreach (var entry in entries) {
+                        warning ("    %s", entry.to_string ());
+                    }
+                }
+            }
+            warning ("Expected setting changes so far:");
+            if (this.expected_setting_changes.gee.size == 0) {
+                warning ("(none)");
+            } else {
+                var changes = this.expected_setting_changes.gee;
+
+                foreach (var section in changes.keys) {
+                    var keys = changes.get (section);
+
+                    warning ("  %s", section);
+                    foreach (var key in keys) {
+                        warning ("    %s", key);
+                    }
+                }
+            }
+        }
+    }
+
+    private static string LOCAL_CONFIG = "user-config-test-local.ini";
+    private static string SYSTEM_CONFIG = "user-config-test-system.ini";
+    private static string GENERAL = "general";
+    private static string FOO = "foo";
+
+    private MainLoop main_loop;
+    private UserConfig config;
+    private bool fail;
+    private WatchData current_watch_data;
+    private uint timeout_id;
+    private HashMap<string, Settings> last_settings;
+
+    private void set_config (string path,
+                             Settings settings = new Settings ()) throws Error {
+        KeyFile key_file = new KeyFile ();
+
+        this.last_settings.set (path, settings);
+
+        if (settings.general_title != null) {
+            key_file.set_string (GENERAL, "title", settings.general_title);
+        }
+        if (settings.general_enabled != null) {
+            key_file.set_boolean (GENERAL, "enabled", settings.general_enabled);
+        }
+        if (settings.general_upnp_enabled != null) {
+            key_file.set_boolean (GENERAL,
+                                  "upnp-enabled",
+                                  settings.general_upnp_enabled);
+        }
+        if (settings.general_iface != null) {
+            key_file.set_string (GENERAL, "interface", settings.general_iface);
+        }
+        if (settings.general_port != null) {
+            key_file.set_integer (GENERAL, "port", settings.general_port);
+        }
+
+        if (settings.foo_title != null) {
+            key_file.set_string (FOO, "title", settings.foo_title);
+        }
+        if (settings.foo_enabled != null) {
+            key_file.set_boolean (FOO, "enabled", settings.foo_enabled);
+        }
+        if (settings.foo_setting != null) {
+            key_file.set_boolean (FOO, "setting", settings.foo_setting);
+        }
+
+        var tmp_path = path + ".tmp";
+        size_t size;
+        var data = key_file.to_data (out size);
+
+        FileUtils.set_contents (tmp_path, data, (ssize_t)size);
+        FileUtils.rename (tmp_path, path);
+    }
+
+    private void remove_config (string path) {
+        FileUtils.unlink (path);
+        this.last_settings.set (path, new Settings ());
+    }
+
+    public UserConfigTest () {
+        this.main_loop = new MainLoop (null, false);
+        this.fail = false;
+        this.timeout_id = 0;
+        this.last_settings = new HashMap<string, Settings> ();
+
+        this.last_settings.set (LOCAL_CONFIG, new Settings ());
+        this.last_settings.set (SYSTEM_CONFIG, new Settings ());
+    }
+
+    private void try_load (bool expect_failure) {
+        var failed = false;
+
+        try {
+            var config = new UserConfig.with_paths (LOCAL_CONFIG,
+                                                    SYSTEM_CONFIG);
+        } catch (Error e) {
+            failed = true;
+        }
+        if (expect_failure != failed) {
+            warning ("Unexpected %s of UserConfig creation.",
+                     (expect_failure ? "success" : "failure"));
+            this.fail = true;
+        }
+    }
+
+    private class ConfigRemover {
+        private UserConfigTest test;
+
+        public ConfigRemover (UserConfigTest test) {
+            this.test = test;
+        }
+
+        ~ConfigRemover () {
+            this.test.remove_config (LOCAL_CONFIG);
+            this.test.remove_config (SYSTEM_CONFIG);
+        }
+    }
+
+    private void test_loading () {
+        var remover = new ConfigRemover (this);
+
+        this.set_config (LOCAL_CONFIG);
+        this.set_config (SYSTEM_CONFIG);
+        this.try_load (false);
+        this.remove_config (LOCAL_CONFIG);
+        this.try_load (false);
+        this.remove_config (SYSTEM_CONFIG);
+        this.try_load (true);
+        // Should not fail when system config does not exist but local
+        // do.
+        // https://bugzilla.gnome.org/show_bug.cgi?id=683959
+
+        // this.set_config (LOCAL_CONFIG);
+        // this.try_load (false);
+    }
+
+    private void data_check () {
+        if (this.current_watch_data.empty ()) {
+            if (this.timeout_id != 0) {
+                Source.remove (this.timeout_id);
+                this.timeout_id = 0;
+            }
+            this.main_loop.quit ();
+        }
+    }
+
+    private void on_configuration_changed (Configuration config,
+                                           ConfigurationEntry entry) {
+        var changes = this.current_watch_data.expected_config_changes.gee;
+
+        if (changes.remove (entry)) {
+            this.data_check ();
+        } else {
+            this.current_watch_data.print_description ();
+            warning ("Unexpected change of configuration entry: %s",
+                     entry.to_string ());
+            this.fail = true;
+        }
+    }
+
+    private void on_section_changed (Configuration config,
+                                     string section,
+                                     SectionEntry entry) {
+        var changes = this.current_watch_data.expected_section_changes.gee;
+
+        if (changes.has_key (section)) {
+            var entries = changes.get (section);
+
+            if (entries.remove (entry)) {
+                if (entries.size == 0) {
+                    changes.remove (section);
+                }
+                this.data_check ();
+            } else {
+                this.current_watch_data.print_description ();
+                warning ("Unexpected change in expected section: %s, " +
+                         "unexpected entry: %s.",
+                         section,
+                         entry.to_string ());
+                this.fail = true;
+            }
+        } else {
+            this.current_watch_data.print_description ();
+            warning ("Unexpected change in unexpected section: %s, entry %s.",
+                     section,
+                     entry.to_string ());
+            this.fail = true;
+        }
+    }
+
+    private void on_setting_changed (Configuration config,
+                                     string section,
+                                     string key) {
+        var changes = this.current_watch_data.expected_setting_changes.gee;
+
+        if (changes.has_key (section)) {
+            var keys = changes.get (section);
+
+            if (keys.remove (key)) {
+                if (keys.size == 0) {
+                    changes.remove (section);
+                }
+                this.data_check ();
+            } else {
+                this.current_watch_data.print_description ();
+                warning ("Unexpected change in expected setting section: %s, " +
+                         "unexpected setting key: %s.",
+                         section,
+                         key);
+                this.fail = true;
+            }
+        } else {
+            this.current_watch_data.print_description ();
+            warning ("Unexpected change in unexpected setting section: %s, " +
+                     "setting key: %s",
+                     section,
+                     key);
+            this.fail = true;
+        }
+    }
+
+    private ArrayList<WatchData> prepare_watch_data () {
+        var data = new ArrayList<WatchData> ();
+        var do_nothing = new SettingsDoNothing (this);
+
+
+        // change nothing, expect no changes.
+        {
+            var desc = "change nothing, expect no changes";
+
+            data.add (new WatchData.no_changes (desc, do_nothing, do_nothing));
+        }
+
+        // set new config but with the same contents as before, expect
+        // no changes.
+        {
+            var desc = "set new config but with the same contents as before, " +
+                "expect no changes";
+            var last_local = new SettingsReplace
+                                        (this,
+                                         this.last_settings.get (LOCAL_CONFIG));
+            var last_system = new SettingsReplace
+                                       (this,
+                                        this.last_settings.get (SYSTEM_CONFIG));
+
+            data.add (new WatchData.no_changes (desc, last_local, last_system));
+        }
+
+        // set empty system config, expect no changes
+        {
+            var desc = "set empty system config, expect no changes";
+            var empty = new SettingsReplace (this, new Settings ());
+
+            data.add (new WatchData.no_changes (desc, do_nothing, empty));
+        }
+
+        // change all possible values in local config, expect lots of
+        // changes
+        {
+            var desc = "change all possible values in local config, expect " +
+                "lots of changes";
+            var config = new ConfigSet ();
+
+            config.gee.add (ConfigurationEntry.UPNP_ENABLED);
+            config.gee.add (ConfigurationEntry.INTERFACE);
+            config.gee.add (ConfigurationEntry.PORT);
+
+            var section = new SectionMap ();
+            var general_section = section.new_values (GENERAL);
+            var foo_section = section.new_values (FOO);
+
+            general_section.add (SectionEntry.TITLE);
+            general_section.add (SectionEntry.ENABLED);
+            foo_section.add (SectionEntry.TITLE);
+            foo_section.add (SectionEntry.ENABLED);
+
+            var setting = new SettingMap ();
+            var foo_setting = setting.new_values (FOO);
+
+            foo_setting.add ("setting");
+
+            var new_local = new SettingsReplace
+                                        (this,
+                                         new Settings ("Changed!",
+                                                       false,
+                                                       false,
+                                                       "Changed!",
+                                                       13,
+                                                       "Changed!",
+                                                       false,
+                                                       false));
+
+            data.add (new WatchData (desc,
+                                     new_local,
+                                     do_nothing,
+                                     config,
+                                     section,
+                                     setting));
+        }
+
+        // add system config back, expect no changes
+        {
+            var desc = "add system config back, expect no changes";
+            var system_default = new SettingsReplace (this,
+                                                      new Settings.default ());
+
+            data.add (new WatchData.no_changes (desc,
+                                                do_nothing,
+                                                system_default));
+        }
+
+        // remove several keys from local config, expect changes for those
+        {
+            var desc = "remove several keys from local config, expect changes" +
+                " for those";
+            var config = new ConfigSet ();
+
+            config.gee.add (ConfigurationEntry.INTERFACE);
+
+            var section = new SectionMap ();
+            var general_section = section.new_values (GENERAL);
+            var foo_section = section.new_values (FOO);
+
+            general_section.add (SectionEntry.TITLE);
+            foo_section.add (SectionEntry.ENABLED);
+
+            var setting = new SettingMap ();
+            var foo_setting = setting.new_values (FOO);
+
+            foo_setting.add ("setting");
+
+            var new_local = new SettingsReplace
+                                        (this,
+                                         new Settings (null,
+                                                       false,
+                                                       false,
+                                                       null,
+                                                       13,
+                                                       "Changed!",
+                                                       null,
+                                                       null));
+
+            data.add (new WatchData (desc,
+                                     new_local,
+                                     do_nothing,
+                                     config,
+                                     section,
+                                     setting));
+        }
+
+        // remove local config, expect changes for the rest of settings
+        {
+            var desc = "remove local config, expect changes for the rest of " +
+                "settings";
+            var config = new ConfigSet ();
+
+            config.gee.add (ConfigurationEntry.UPNP_ENABLED);
+            config.gee.add (ConfigurationEntry.PORT);
+
+            var section = new SectionMap ();
+            var general_section = section.new_values (GENERAL);
+            var foo_section = section.new_values (FOO);
+
+            general_section.add (SectionEntry.ENABLED);
+            foo_section.add (SectionEntry.TITLE);
+
+            var setting = new SettingMap ();
+
+            data.add (new WatchData (desc,
+                                     new SettingsRemove (this),
+                                     do_nothing,
+                                     config,
+                                     section,
+                                     setting));
+        }
+
+        return data;
+    }
+
+    private void test_watching () {
+        var remover = new ConfigRemover (this);
+        var full_settings = new Settings.default ();
+
+        this.set_config (LOCAL_CONFIG,
+                         full_settings);
+        this.set_config (SYSTEM_CONFIG,
+                         full_settings);
+        this.config = new UserConfig.with_paths (LOCAL_CONFIG, SYSTEM_CONFIG);
+        this.config.configuration_changed.connect
+                                        (this.on_configuration_changed);
+        this.config.section_changed.connect (this.on_section_changed);
+        this.config.setting_changed.connect (this.on_setting_changed);
+
+        // this have to be after setting local and system config
+        var watch_data_array = this.prepare_watch_data ();
+
+        foreach (var watch_data in watch_data_array) {
+            this.current_watch_data = watch_data;
+
+            this.timeout_id = Timeout.add_seconds (2, () => {
+                if (!this.current_watch_data.empty ()) {
+                    this.current_watch_data.print_description ();
+                    warning ("Test timed out and not all expected changes " +
+                             "happened.");
+                    this.current_watch_data.print_expectations ();
+                    this.fail = true;
+                }
+                this.timeout_id = 0;
+                this.main_loop.quit ();
+                return false;
+            });
+
+            watch_data.prepare_setup ();
+            this.main_loop.run ();
+            if (this.fail) {
+                return;
+            }
+        }
+    }
+
+    public int run () throws Error {
+        test_loading ();
+        test_watching ();
+
+        if (this.fail) {
+            return 1;
+        }
+        return 0;
+    }
+
+    public static int main (string[] args) {
+        var test = new UserConfigTest ();
+
+        try {
+            return test.run ();
+        } catch (Error e) {
+            return 1;
+        }
+    }
+}
diff --git a/tests/rygel-user-config.vala b/tests/rygel-user-config.vala
new file mode 120000
index 0000000..fe0e9c6
--- /dev/null
+++ b/tests/rygel-user-config.vala
@@ -0,0 +1 @@
+../src/rygel/rygel-user-config.vala
\ No newline at end of file



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