2 * Copyright (C) 2012 Intel Corporation
4 * Author: Krzesimir Nowak <krnowak@openismus.com>
6 * This file is part of Rygel.
8 * Rygel is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * Rygel is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 public class Rygel.UserConfigTest : GLib.Object {
27 // pitiful Vala with no typedefs...
28 public class ConfigSet : GLib.Object {
29 public HashSet<ConfigurationEntry> gee;
32 this.gee = new HashSet<ConfigurationEntry> ();
36 public class SectionMap : GLib.Object {
37 public HashMap<string, HashSet<SectionEntry> > gee;
39 public SectionMap () {
40 this.gee = new HashMap<string, HashSet<SectionEntry> > ();
43 public HashSet<SectionEntry> new_values (string section) {
44 var values = new HashSet<SectionEntry> ();
46 this.gee.set (section, values);
52 public class SettingMap : GLib.Object {
53 public HashMap<string, HashSet<string> > gee;
55 public SettingMap () {
56 this.gee = new HashMap<string, HashSet<string> > ();
59 public HashSet<string> new_values (string section) {
60 var values = new HashSet<string> ();
62 this.gee.set (section, values);
68 private class Settings : GLib.Object {
69 public string? general_title;
70 public bool? general_enabled;
71 public bool? general_upnp_enabled;
72 public string? general_iface;
73 public int? general_port;
74 public string? foo_title;
75 public bool? foo_enabled;
76 public bool? foo_setting;
78 private void initialize (string? general_title = null,
79 bool? general_enabled = null,
80 bool? general_upnp_enabled = null,
81 string? general_iface = null,
82 int? general_port = null,
83 string? foo_title = null,
84 bool? foo_enabled = null,
85 bool? foo_setting = null) {
86 this.general_title = general_title;
87 this.general_enabled = general_enabled;
88 this.general_upnp_enabled = general_upnp_enabled;
89 this.general_iface = general_iface;
90 this.general_port = general_port;
91 this.foo_title = foo_title;
92 this.foo_enabled = foo_enabled;
93 this.foo_setting = foo_setting;
96 public Settings (string? general_title = null,
97 bool? general_enabled = null,
98 bool? general_upnp_enabled = null,
99 string? general_iface = null,
100 int? general_port = null,
101 string? foo_title = null,
102 bool? foo_enabled = null,
103 bool? foo_setting = null) {
104 this.initialize (general_title,
106 general_upnp_enabled,
114 public Settings.default () {
115 this.initialize ("General",
126 private abstract class SettingsAction : GLib.Object {
127 protected UserConfigTest test;
129 SettingsAction (UserConfigTest test) {
132 public abstract void perform (string config);
135 private class SettingsDoNothing : SettingsAction {
136 public SettingsDoNothing (UserConfigTest test) {
140 public override void perform (string config) {}
143 private class SettingsReplace : SettingsAction {
144 private Settings settings;
146 public SettingsReplace (UserConfigTest test,
149 this.settings = settings;
152 public override void perform (string config) {
154 this.test.set_config (config,
156 } catch (GLib.Error error) {
157 assert_not_reached ();
162 private class SettingsRemove : SettingsAction {
163 public SettingsRemove (UserConfigTest test) {
167 public override void perform (string config) {
168 this.test.remove_config (config);
172 private class WatchData : GLib.Object {
173 public string description;
174 public SettingsAction local_action;
175 public SettingsAction system_action;
176 public ConfigSet expected_config_changes;
177 public SectionMap expected_section_changes;
178 public SettingMap expected_setting_changes;
180 private bool description_printed;
182 private void initialize (string description,
183 SettingsAction local_action,
184 SettingsAction system_action,
185 ConfigSet expected_config_changes,
186 SectionMap expected_section_changes,
187 SettingMap expected_setting_changes) {
188 this.description = description;
189 this.local_action = local_action;
190 this.system_action = system_action;
191 this.expected_config_changes = expected_config_changes;
192 this.expected_section_changes = expected_section_changes;
193 this.expected_setting_changes = expected_setting_changes;
194 this.description_printed = false;
197 public WatchData (string description,
198 SettingsAction local_action,
199 SettingsAction system_action,
200 ConfigSet expected_config_changes,
201 SectionMap expected_section_changes,
202 SettingMap expected_setting_changes) {
203 this.initialize (description,
206 expected_config_changes,
207 expected_section_changes,
208 expected_setting_changes);
211 public WatchData.no_changes (string description,
212 SettingsAction local_action,
213 SettingsAction system_action) {
214 this.initialize (description,
222 public bool empty () {
223 return (this.expected_config_changes.gee.size == 0 &&
224 this.expected_section_changes.gee.size == 0 &&
225 this.expected_setting_changes.gee.size == 0);
228 public void prepare_setup () {
229 this.local_action.perform (LOCAL_CONFIG);
230 this.system_action.perform (SYSTEM_CONFIG);
233 public void print_description () {
234 if (!this.description_printed) {
235 this.description_printed = true;
236 warning ("Test case: %s.", this.description);
240 public void print_expectations () {
241 warning ("Expected configuration changes so far:");
242 if (this.expected_config_changes.gee.size == 0) {
245 foreach (var entry in this.expected_config_changes.gee) {
246 warning (" %s", entry.to_string ());
249 warning ("Expected section changes so far:");
250 if (this.expected_section_changes.gee.size == 0) {
253 var changes = this.expected_section_changes.gee;
255 foreach (var section in changes.keys) {
256 var entries = changes.get (section);
258 warning (" %s", section);
259 foreach (var entry in entries) {
260 warning (" %s", entry.to_string ());
264 warning ("Expected setting changes so far:");
265 if (this.expected_setting_changes.gee.size == 0) {
268 var changes = this.expected_setting_changes.gee;
270 foreach (var section in changes.keys) {
271 var keys = changes.get (section);
273 warning (" %s", section);
274 foreach (var key in keys) {
275 warning (" %s", key);
282 private static string LOCAL_CONFIG = "user-config-test-local.ini";
283 private static string SYSTEM_CONFIG = "user-config-test-system.ini";
284 private static string GENERAL = "general";
285 private static string FOO = "foo";
287 private MainLoop main_loop;
288 private UserConfig config;
290 private WatchData current_watch_data;
291 private uint timeout_id;
292 private HashMap<string, Settings> last_settings;
294 private void set_config (string path,
295 Settings settings = new Settings ()) throws Error {
296 KeyFile key_file = new KeyFile ();
298 this.last_settings.set (path, settings);
300 if (settings.general_title != null) {
301 key_file.set_string (GENERAL, "title", settings.general_title);
303 if (settings.general_enabled != null) {
304 key_file.set_boolean (GENERAL, "enabled", settings.general_enabled);
306 if (settings.general_upnp_enabled != null) {
307 key_file.set_boolean (GENERAL,
309 settings.general_upnp_enabled);
311 if (settings.general_iface != null) {
312 key_file.set_string (GENERAL, "interface", settings.general_iface);
314 if (settings.general_port != null) {
315 key_file.set_integer (GENERAL, "port", settings.general_port);
318 if (settings.foo_title != null) {
319 key_file.set_string (FOO, "title", settings.foo_title);
321 if (settings.foo_enabled != null) {
322 key_file.set_boolean (FOO, "enabled", settings.foo_enabled);
324 if (settings.foo_setting != null) {
325 key_file.set_boolean (FOO, "setting", settings.foo_setting);
328 var tmp_path = path + ".tmp";
330 var data = key_file.to_data (out size);
332 FileUtils.set_contents (tmp_path, data, (ssize_t)size);
333 FileUtils.rename (tmp_path, path);
336 private void remove_config (string path) {
337 FileUtils.unlink (path);
338 this.last_settings.set (path, new Settings ());
341 public UserConfigTest () {
342 this.main_loop = new MainLoop (null, false);
345 this.last_settings = new HashMap<string, Settings> ();
347 this.last_settings.set (LOCAL_CONFIG, new Settings ());
348 this.last_settings.set (SYSTEM_CONFIG, new Settings ());
351 private void try_load (bool expect_failure) {
355 var config = new UserConfig.with_paths (LOCAL_CONFIG,
357 assert (config != null);
361 if (expect_failure != failed) {
362 warning ("Unexpected %s of UserConfig creation.",
363 (expect_failure ? "success" : "failure"));
368 private class ConfigRemover {
369 private UserConfigTest test;
371 public ConfigRemover (UserConfigTest test) {
376 this.test.remove_config (LOCAL_CONFIG);
377 this.test.remove_config (SYSTEM_CONFIG);
381 private void test_loading () {
382 var remover = new ConfigRemover (this);
383 assert (remover != null);
386 this.set_config (LOCAL_CONFIG);
387 } catch (GLib.Error error) {
388 assert_not_reached ();
392 this.set_config (SYSTEM_CONFIG);
393 } catch (GLib.Error error) {
394 assert_not_reached ();
396 this.try_load (false);
397 this.remove_config (LOCAL_CONFIG);
398 this.try_load (false);
399 this.remove_config (SYSTEM_CONFIG);
400 this.try_load (true);
401 // Should not fail when system config does not exist but local
403 // https://bugzilla.gnome.org/show_bug.cgi?id=683959
405 // this.set_config (LOCAL_CONFIG);
406 // this.try_load (false);
409 private void data_check () {
410 if (this.current_watch_data.empty ()) {
411 if (this.timeout_id != 0) {
412 Source.remove (this.timeout_id);
415 this.main_loop.quit ();
419 private void on_configuration_changed (Configuration config,
420 ConfigurationEntry entry) {
421 var changes = this.current_watch_data.expected_config_changes.gee;
423 if (changes.remove (entry)) {
426 this.current_watch_data.print_description ();
427 warning ("Unexpected change of configuration entry: %s",
433 private void on_section_changed (Configuration config,
435 SectionEntry entry) {
436 var changes = this.current_watch_data.expected_section_changes.gee;
438 if (changes.has_key (section)) {
439 var entries = changes.get (section);
441 if (entries.remove (entry)) {
442 if (entries.size == 0) {
443 changes.unset (section);
447 this.current_watch_data.print_description ();
448 warning ("Unexpected change in expected section: %s, " +
449 "unexpected entry: %s.",
455 this.current_watch_data.print_description ();
456 warning ("Unexpected change in unexpected section: %s, entry %s.",
463 private void on_setting_changed (Configuration config,
466 var changes = this.current_watch_data.expected_setting_changes.gee;
468 if (changes.has_key (section)) {
469 var keys = changes.get (section);
471 if (keys.remove (key)) {
472 if (keys.size == 0) {
473 changes.unset (section);
477 this.current_watch_data.print_description ();
478 warning ("Unexpected change in expected setting section: %s, " +
479 "unexpected setting key: %s.",
485 this.current_watch_data.print_description ();
486 warning ("Unexpected change in unexpected setting section: %s, " +
494 private ArrayList<WatchData> prepare_watch_data () {
495 var data = new ArrayList<WatchData> ();
496 var do_nothing = new SettingsDoNothing (this);
499 // change nothing, expect no changes.
501 var desc = "change nothing, expect no changes";
503 data.add (new WatchData.no_changes (desc, do_nothing, do_nothing));
506 // set new config but with the same contents as before, expect
509 var desc = "set new config but with the same contents as before, " +
511 var last_local = new SettingsReplace
513 this.last_settings.get (LOCAL_CONFIG));
514 var last_system = new SettingsReplace
516 this.last_settings.get (SYSTEM_CONFIG));
518 data.add (new WatchData.no_changes (desc, last_local, last_system));
521 // set empty system config, expect no changes
523 var desc = "set empty system config, expect no changes";
524 var empty = new SettingsReplace (this, new Settings ());
526 data.add (new WatchData.no_changes (desc, do_nothing, empty));
529 // change all possible values in local config, expect lots of
532 var desc = "change all possible values in local config, expect " +
534 var config = new ConfigSet ();
536 config.gee.add (ConfigurationEntry.UPNP_ENABLED);
537 config.gee.add (ConfigurationEntry.INTERFACE);
538 config.gee.add (ConfigurationEntry.PORT);
540 var section = new SectionMap ();
541 var general_section = section.new_values (GENERAL);
542 var foo_section = section.new_values (FOO);
544 general_section.add (SectionEntry.TITLE);
545 general_section.add (SectionEntry.ENABLED);
546 foo_section.add (SectionEntry.TITLE);
547 foo_section.add (SectionEntry.ENABLED);
549 var setting = new SettingMap ();
550 var foo_setting = setting.new_values (FOO);
552 foo_setting.add ("setting");
554 var new_local = new SettingsReplace
556 new Settings ("Changed!",
565 data.add (new WatchData (desc,
573 // add system config back, expect no changes
575 var desc = "add system config back, expect no changes";
576 var system_default = new SettingsReplace (this,
577 new Settings.default ());
579 data.add (new WatchData.no_changes (desc,
584 // remove several keys from local config, expect changes for those
586 var desc = "remove several keys from local config, expect changes" +
588 var config = new ConfigSet ();
590 config.gee.add (ConfigurationEntry.INTERFACE);
592 var section = new SectionMap ();
593 var general_section = section.new_values (GENERAL);
594 var foo_section = section.new_values (FOO);
596 general_section.add (SectionEntry.TITLE);
597 foo_section.add (SectionEntry.ENABLED);
599 var setting = new SettingMap ();
600 var foo_setting = setting.new_values (FOO);
602 foo_setting.add ("setting");
604 var new_local = new SettingsReplace
615 data.add (new WatchData (desc,
623 // remove local config, expect changes for the rest of settings
625 var desc = "remove local config, expect changes for the rest of " +
627 var config = new ConfigSet ();
629 config.gee.add (ConfigurationEntry.UPNP_ENABLED);
630 config.gee.add (ConfigurationEntry.PORT);
632 var section = new SectionMap ();
633 var general_section = section.new_values (GENERAL);
634 var foo_section = section.new_values (FOO);
636 general_section.add (SectionEntry.ENABLED);
637 foo_section.add (SectionEntry.TITLE);
639 var setting = new SettingMap ();
641 data.add (new WatchData (desc,
642 new SettingsRemove (this),
652 private void test_watching () {
653 var remover = new ConfigRemover (this);
654 assert (remover != null);
655 var full_settings = new Settings.default ();
656 assert (full_settings != null);
659 this.set_config (LOCAL_CONFIG,
661 } catch (GLib.Error error) {
662 assert_not_reached ();
666 this.set_config (SYSTEM_CONFIG,
668 } catch (GLib.Error error) {
669 assert_not_reached ();
673 this.config = new UserConfig.with_paths (LOCAL_CONFIG, SYSTEM_CONFIG);
674 } catch (GLib.Error error) {
675 assert_not_reached ();
678 assert (this.config != null);
679 this.config.configuration_changed.connect
680 (this.on_configuration_changed);
681 this.config.section_changed.connect (this.on_section_changed);
682 this.config.setting_changed.connect (this.on_setting_changed);
684 // this have to be after setting local and system config
685 var watch_data_array = this.prepare_watch_data ();
687 foreach (var watch_data in watch_data_array) {
688 this.current_watch_data = watch_data;
690 this.timeout_id = Timeout.add_seconds (2, () => {
691 if (!this.current_watch_data.empty ()) {
692 this.current_watch_data.print_description ();
693 warning ("Test timed out and not all expected changes " +
695 this.current_watch_data.print_expectations ();
699 this.main_loop.quit ();
703 watch_data.prepare_setup ();
704 this.main_loop.run ();
711 public int run () throws Error {
721 public static int main (string[] args) {
722 var test = new UserConfigTest ();