about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2014-04-14 23:01:57 +0100
committerJames Booth <boothj5@gmail.com>2014-04-14 23:01:57 +0100
commit241973700697abb60104c656a0aacfd182eb2316 (patch)
treea9aa0dcf7576a819a835e48d6c35c4c17de32552
parent8d77930eceba6841673605f7df5083657a0ecd28 (diff)
downloadprofani-tty-241973700697abb60104c656a0aacfd182eb2316.tar.gz
Check for duplicate options in option parser
-rw-r--r--src/tools/parser.c21
-rw-r--r--tests/test_parser.c20
-rw-r--r--tests/test_parser.h3
-rw-r--r--tests/testsuite.c1
4 files changed, 42 insertions, 3 deletions
diff --git a/src/tools/parser.c b/src/tools/parser.c
index 375572e0..b4403d06 100644
--- a/src/tools/parser.c
+++ b/src/tools/parser.c
@@ -385,14 +385,31 @@ parse_options(gchar **args, int start, GList *keys, gboolean *res)
         return options;
     }
 
-    // check each option is valid and has value, failure if not
+    // validate options
     int curr;
+    GList *found_keys = NULL;
     for (curr = start; curr < g_strv_length(args); curr+= 2) {
-        if ((g_list_find(keys, args[curr]) == NULL) || (args[curr+1] == NULL)) {
+        // check if option valid
+        if (g_list_find(keys, args[curr]) == NULL) {
             *res = FALSE;
             return options;
         }
+
+        // check if duplicate
+        if (g_list_find(found_keys, args[curr]) != NULL) {
+            *res = FALSE;
+            return options;
+        }
+
+        // check value given
+        if (args[curr+1] == NULL) {
+            *res = FALSE;
+            return options;
+        }
+
+        found_keys = g_list_append(found_keys, args[curr]);
     }
+    g_list_free(found_keys);
 
     // create map
     options = g_hash_table_new(g_str_hash, g_str_equal);
diff --git a/tests/test_parser.c b/tests/test_parser.c
index 1309e8e1..6e1d4cde 100644
--- a/tests/test_parser.c
+++ b/tests/test_parser.c
@@ -667,4 +667,24 @@ parse_options_when_unknown_opt_sets_error(void **state)
     assert_false(res);
 
     options_destroy(options);
+}
+
+void
+parse_options_with_duplicated_option_sets_error(void **state)
+{
+    gchar *args[] = { "cmd1", "cmd2", "opt1", "val1", "opt2", "val2", "opt1", "val3", NULL };
+
+    GList *keys = NULL;
+    keys = g_list_append(keys, "opt1");
+    keys = g_list_append(keys, "opt2");
+    keys = g_list_append(keys, "opt3");
+
+    gboolean res = TRUE;
+
+    GHashTable *options = parse_options(args, 2, keys, &res);
+
+    assert_null(options);
+    assert_false(res);
+
+    options_destroy(options);
 }
\ No newline at end of file
diff --git a/tests/test_parser.h b/tests/test_parser.h
index 70b94b50..51d768fe 100644
--- a/tests/test_parser.h
+++ b/tests/test_parser.h
@@ -46,4 +46,5 @@ void parse_options_when_opt2_no_val_sets_error(void **state);
 void parse_options_when_two_returns_map(void **state);
 void parse_options_when_opt3_no_val_sets_error(void **state);
 void parse_options_when_three_returns_map(void **state);
-void parse_options_when_unknown_opt_sets_error(void **state);
\ No newline at end of file
+void parse_options_when_unknown_opt_sets_error(void **state);
+void parse_options_with_duplicated_option_sets_error(void **state);
diff --git a/tests/testsuite.c b/tests/testsuite.c
index c6577410..05f03188 100644
--- a/tests/testsuite.c
+++ b/tests/testsuite.c
@@ -173,6 +173,7 @@ int main(int argc, char* argv[]) {
         unit_test(parse_options_when_opt3_no_val_sets_error),
         unit_test(parse_options_when_three_returns_map),
         unit_test(parse_options_when_unknown_opt_sets_error),
+        unit_test(parse_options_with_duplicated_option_sets_error),
 
         unit_test(empty_list_when_none_added),
         unit_test(contains_one_element),