[dconf: 1/6] bin: Consistently validate the number of arguments



commit d9748d753f34a030ee483e7723037ec4d335fae3
Author: Tomasz Miąsko <tomasz miasko gmail com>
Date:   Mon Nov 12 00:00:00 2018 +0000

    bin: Consistently validate the number of arguments

 bin/dconf-dump.vala |  8 +++++
 bin/dconf.vala      | 38 ++++++++++++++++++++++
 tests/test-dconf.py | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 137 insertions(+)
---
diff --git a/bin/dconf-dump.vala b/bin/dconf-dump.vala
index d63e3eb..26f62d0 100644
--- a/bin/dconf-dump.vala
+++ b/bin/dconf-dump.vala
@@ -39,6 +39,10 @@ void dconf_dump (string[] args) throws Error {
 
        DConf.verify_dir (dir);
 
+       if (args[3] != null) {
+               throw new OptionError.FAILED ("too many arguments");
+       }
+
        add_to_keyfile (kf, client, dir);
        print ("%s", kf.to_data ());
 }
@@ -62,6 +66,10 @@ void dconf_load (string[] args) throws Error {
        var dir = args[2];
        DConf.verify_dir (dir);
 
+       if (args[3] != null) {
+               throw new OptionError.FAILED ("too many arguments");
+       }
+
        var changeset = new DConf.Changeset ();
        var kf = keyfile_from_stdin ();
 
diff --git a/bin/dconf.vala b/bin/dconf.vala
index 8b0f211..1f0109c 100644
--- a/bin/dconf.vala
+++ b/bin/dconf.vala
@@ -173,6 +173,10 @@ void dconf_read (string?[] args) throws Error {
 
        DConf.verify_key (key);
 
+       if (args[index + 1] != null) {
+               throw new OptionError.FAILED ("too many arguments");
+       }
+
        var result = client.read_full (key, flags, null);
 
        if (result != null) {
@@ -200,6 +204,10 @@ void dconf_list_locks (string?[] args) throws Error {
 
        DConf.verify_dir (dir);
 
+       if (args[3] != null) {
+               throw new OptionError.FAILED ("too many arguments");
+       }
+
        foreach (var item in client.list_locks (dir)) {
                print ("%s\n", item);
        }
@@ -208,10 +216,21 @@ void dconf_list_locks (string?[] args) throws Error {
 void dconf_write (string?[] args) throws Error {
        var client = new DConf.Client ();
        var key = args[2];
+       if (key == null) {
+               throw new OptionError.FAILED ("key not specified");
+       }
+
        var val = args[3];
+       if (val == null) {
+               throw new OptionError.FAILED ("value not specified");
+       }
 
        DConf.verify_key (key);
 
+       if (args[4] != null) {
+               throw new OptionError.FAILED ("too many arguments");
+       }
+
        client.write_sync (key, Variant.parse (null, val));
 }
 
@@ -229,6 +248,10 @@ void dconf_reset (string?[] args) throws Error {
 
        DConf.verify_path (path);
 
+       if (args[index + 1] != null) {
+               throw new OptionError.FAILED ("too many arguments");
+       }
+
        if (DConf.is_dir (path) && !force) {
                throw new OptionError.FAILED ("-f must be given to (recursively) reset entire dirs");
        }
@@ -259,6 +282,10 @@ void dconf_watch (string?[] args) throws Error {
 
        DConf.verify_path (path);
 
+       if (args[3] != null) {
+               throw new OptionError.FAILED ("too many arguments");
+       }
+
        client.changed.connect (watch_function);
        client.watch_sync (path);
 
@@ -274,7 +301,18 @@ void dconf_blame (string?[] args) throws Error {
 
 void dconf_complete (string[] args) throws Error {
        var suffix = args[2];
+       if (suffix == null) {
+               throw new OptionError.FAILED ("suffix not specified");
+       }
+
        var path = args[3];
+       if (path == null) {
+               throw new OptionError.FAILED ("path not specified");
+       }
+
+       if (args[4] != null) {
+               throw new OptionError.FAILED ("too many arguments");
+       }
 
        if (path == "") {
                print ("/\n");
diff --git a/tests/test-dconf.py b/tests/test-dconf.py
index cc31ef2..e7ff747 100755
--- a/tests/test-dconf.py
+++ b/tests/test-dconf.py
@@ -147,6 +147,97 @@ class DBusTest(unittest.TestCase):
 
         self.temporary_dir.cleanup()
 
+    def test_invalid_usage(self):
+        """Invalid dconf usage results in non-zero exit code and help message.
+        """
+        cases = [
+            # No command:
+            [],
+
+            # Invalid command:
+            ['no-such-command'],
+
+            # Too many arguments:
+            ['blame', 'a'],
+
+            # Missing arguments:
+            ['compile'],
+            ['compile', 'output'],
+            # Too many arguments:
+            ['compile', 'output', 'dir1', 'dir2'],
+
+            # Missing arguments:
+            ['_complete'],
+            ['_complete', ''],
+            # Too many arguments:
+            ['_complete', '', '/', '/'],
+
+            # Missing argument:
+            ['dump'],
+            # Dir is required:
+            ['dump', '/key'],
+            # Too many arguments:
+            ['dump', '/a/', '/b/'],
+
+            # Missing argument:
+            ['list'],
+            # Dir is required:
+            ['list', '/foo/bar'],
+            # Too many arguments:
+            ['list', '/foo', '/bar'],
+
+            # Missing argument:
+            ['list-locks'],
+            # Dir is required:
+            ['list-locks', '/key'],
+            # Too many arguments:
+            ['list-locks', '/a/', '/b/'],
+
+            # Missing argument:
+            ['load'],
+            # Dir is required:
+            ['load', '/key'],
+            # Too many arguments:
+            ['load', '/a/', '/b/'],
+
+            # Missing argument:
+            ['read'],
+            # Key is required:
+            ['read', '/dir/'],
+            # Too many arguments:
+            ['read', '/a', '/b'],
+            ['read', '-d', '/a', '/b'],
+
+            # Missing arguments:
+            ['reset'],
+            # Invalid path:
+            ['reset', 'test/test'],
+            # Too many arguments:
+            ['reset', '/test', '/test'],
+            ['reset', '-f', '/', '/'],
+
+            # Missing arguments:
+            ['watch'],
+            # Invalid path:
+            ['watch', 'foo'],
+            # Too many arguments:
+            ['watch', '/a', '/b'],
+
+            # Missing arguments:
+            ['write'],
+            ['write', '/key'],
+            # Invalid value:
+            ['write', '/key', 'not-a-gvariant-value'],
+            # Too many arguments:
+            ['write', '/key', '1', '2'],
+        ]
+
+        for args in cases:
+            with self.subTest(args=args):
+                with self.assertRaises(subprocess.CalledProcessError) as cm:
+                    dconf(*args, stderr=subprocess.PIPE)
+                self.assertRegex(cm.exception.stderr, 'Usage:')
+
     def test_read_nonexisiting(self):
         """Reading missing key produces no output. """
 


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