diff options
-rw-r--r-- | src/reference_tree.ml | 28 | ||||
-rw-r--r-- | test/data/interface_definition_sample.xml | 17 | ||||
-rw-r--r-- | test/reference_tree_test.ml | 10 |
3 files changed, 47 insertions, 8 deletions
diff --git a/src/reference_tree.ml b/src/reference_tree.ml index 5243e82..61e1efa 100644 --- a/src/reference_tree.ml +++ b/src/reference_tree.ml @@ -127,7 +127,18 @@ let load_from_xml reftree file = (* Validation function *) -(* A path can be created in the config tree unless: +let has_illegal_characters name = + (** Checks if string name has illegal characters in it. + All whitespace, curly braces, square brackets, and quotes + are disallowed due to their special significance to the curly config + format parser *) + try Some (Pcre.get_substring (Pcre.exec ~pat:"[\\s\\{\\}\\[\\]\"\'#]" name) 0) + with Not_found -> None + +(** Takes a list of string that represents a configuration path that may have + node value at the end, validates it, and splits it into path and value parts. + + A list of strings is a valid path that can be created in the config tree unless: 1. It's a tag node without a child 2. It's a non-valueless leaf node without a value 3. It's a valueless node with a value @@ -156,12 +167,15 @@ let rec validate_path validators_dir node path = | Tag -> (match path with | p :: p' :: ps -> - if (Value_checker.validate_any validators_dir data.constraints p) then - let child = Vytree.find node p' in - (match child with - | Some c -> aux c ps (p' :: p :: acc) - | None -> raise (Validation_error (Printf.sprintf "Node %s has no child %s" (show_path acc) p'))) - else raise (Validation_error (Printf.sprintf "%s is not a valid child name for node %s" p (show_path acc))) + (match (has_illegal_characters p) with + | Some c -> raise (Validation_error (Printf.sprintf "Illegal character \"%s\" in node name \"%s\"" c p)) + | None -> + if (Value_checker.validate_any validators_dir data.constraints p) then + let child = Vytree.find node p' in + (match child with + | Some c -> aux c ps (p' :: p :: acc) + | None -> raise (Validation_error (Printf.sprintf "Node %s has no child %s" (show_path acc) p'))) + else raise (Validation_error (Printf.sprintf "%s is not a valid child name for node %s" p (show_path acc)))) | [p] -> if (Value_checker.validate_any validators_dir data.constraints p) then (List.rev acc, None) else raise (Validation_error (Printf.sprintf "Node %s has no child %s" (show_path acc) p)) | _ -> raise (Validation_error (Printf.sprintf "Path %s is incomplete" (show_path acc)))) diff --git a/test/data/interface_definition_sample.xml b/test/data/interface_definition_sample.xml index c6185c0..292231e 100644 --- a/test/data/interface_definition_sample.xml +++ b/test/data/interface_definition_sample.xml @@ -60,4 +60,21 @@ </node> </children> </node> + <node name="interfaces"> + <children> + <tagNode name="ethernet"> + <properties> + <!-- no constraint, for testing if tag nodes with invalid characters in names + are detected --> + </properties> + <children> + <leafNode name="disable"> + <properties> + <valueless/> + </properties> + </leafNode> + </children> + </tagNode> + </children> + </node> </interfaceDefinition> diff --git a/test/reference_tree_test.ml b/test/reference_tree_test.ml index 6dfac5a..8002bdf 100644 --- a/test/reference_tree_test.ml +++ b/test/reference_tree_test.ml @@ -10,7 +10,8 @@ let raises_validation_error f = let test_load_valid_definition test_ctxt = let r = Vytree.make default_data "root" in let r = load_from_xml r (in_testdata_dir test_ctxt ["interface_definition_sample.xml"]) in - assert_equal (Vytree.list_children r) ["system"] + assert_equal (Vylist.in_list (Vytree.list_children r) "system") true; + assert_equal (Vylist.in_list (Vytree.list_children r) "interfaces") true (* Path validation tests *) let test_validate_path_leaf_valid test_ctxt = @@ -34,6 +35,12 @@ let test_validate_path_tag_node_complete_valid test_ctxt = assert_equal (validate_path (get_dir test_ctxt) r ["system"; "login"; "user"; "test"; "full-name"; "test user"]) (["system"; "login"; "user"; "test"; "full-name";], Some "test user") +let test_validate_path_tag_node_illegal_characters test_ctxt = + let r = Vytree.make default_data "root" in + let r = load_from_xml r (in_testdata_dir test_ctxt ["interface_definition_sample.xml"]) in + (* the space in "eth 0" is on purpose *) + assert_equal (raises_validation_error (fun () -> ignore @@ validate_path (get_dir test_ctxt) r ["interfaces"; "ethernet"; "eth 0"; "disable"])) true + let test_validate_path_tag_node_invalid_name test_ctxt = let r = Vytree.make default_data "root" in let r = load_from_xml r (in_testdata_dir test_ctxt ["interface_definition_sample.xml"]) in @@ -157,6 +164,7 @@ let suite = "test_validate_path_leaf_valid" >:: test_validate_path_leaf_valid; "test_validate_path_leaf_invalid" >:: test_validate_path_leaf_invalid; "test_validate_path_leaf_incomplete" >:: test_validate_path_leaf_incomplete; + "test_validate_path_tag_node_illegal_characters" >:: test_validate_path_tag_node_illegal_characters; "test_validate_path_tag_node_complete_valid" >:: test_validate_path_tag_node_complete_valid; "test_validate_path_tag_node_invalid_name" >:: test_validate_path_tag_node_invalid_name; "test_validate_path_tag_node_incomplete" >:: test_validate_path_tag_node_incomplete; |