From c02661b7a8151a49a77c39241b040aa9bdb30223 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 17 Nov 2019 19:39:09 +0100
Subject: Fixed the search of Yaml nodes.

---
 plugins/yaml/node.c      | 61 ++++++++++++++++++++++++----------------------
 tests/plugins/yamlrdr.py | 63 +++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 91 insertions(+), 33 deletions(-)

diff --git a/plugins/yaml/node.c b/plugins/yaml/node.c
index 57eb3d2..3dc6ec0 100644
--- a/plugins/yaml/node.c
+++ b/plugins/yaml/node.c
@@ -284,65 +284,64 @@ void _g_yaml_node_find_by_path(GYamlNode *node, const char *path, GYamlNode ***n
 {
     GYamlLine *line;                        /* Ligne Yaml liée au noeud    */
     const char *key;                        /* Clef associée au noeud      */
-    bool matched;                           /* Correspondance établie ?    */
     char *next;                             /* Prochaine partie du chemin  */
     size_t cmplen;                          /* Etendue de la comparaison   */
     int ret;                                /* Bilan d'une comparaison     */
     GYamlCollection *collec;                /* Collection de noeuds        */
 
+    if (path[0] == '\0')
+        goto exit;
+
+    line = g_yaml_node_get_yaml_line(node);
+
     if (path[0] == '/')
+    {
         path++;
 
-    /* Correspondance au niveau du noeud ? */
+        if (path[0] == '\0')
+            goto matched;
 
-    line = g_yaml_node_get_yaml_line(node);
+    }
+
+    /* Correspondance au niveau du noeud ? */
 
     if (line != NULL)
     {
         key = g_yaml_line_get_key(line);
 
-        if (path[0] == '\0')
-            matched = true;
+        next = strchr(path, '/');
+
+        if (next == NULL)
+            ret = strcmp(path, key);
 
         else
         {
-            next = strchr(path, '/');
-
-            cmplen = (next == NULL ? strlen(path) : next - path);
+            cmplen = next - path;
 
             if (cmplen == 0)
                 goto cont;
 
             ret = strncmp(path, key, cmplen);
 
-            if (ret != 0)
-                goto done;
-
-            else
-            {
-                if (next == NULL)
-                    matched = true;
-
-                else
-                {
-                    path += cmplen;
-                    goto cont;
-                }
+        }
 
-            }
+        if (ret != 0)
+            goto done;
 
+        else if (next != NULL)
+        {
+            path += cmplen;
+            goto cont;
         }
 
-        if (matched)
-        {
-            *nodes = realloc(*nodes, ++(*count) * sizeof(GYamlNode **));
+ matched:
 
-            g_object_ref(G_OBJECT(node));
-            (*nodes)[*count - 1] = node;
+        *nodes = realloc(*nodes, ++(*count) * sizeof(GYamlNode **));
 
-            goto done;
+        g_object_ref(G_OBJECT(node));
+        (*nodes)[*count - 1] = node;
 
-        }
+        goto done;
 
     }
 
@@ -363,6 +362,10 @@ void _g_yaml_node_find_by_path(GYamlNode *node, const char *path, GYamlNode ***n
     if (line != NULL)
         g_object_unref(G_OBJECT(line));
 
+ exit:
+
+    ;
+
 }
 
 
diff --git a/tests/plugins/yamlrdr.py b/tests/plugins/yamlrdr.py
index 103d6e8..eeae032 100644
--- a/tests/plugins/yamlrdr.py
+++ b/tests/plugins/yamlrdr.py
@@ -52,10 +52,24 @@ root:
 
 '''
 
+        cls._mixed = tempfile.NamedTemporaryFile()
+
+        cls._mixed_data = b'''
+root:
+  - a: av
+    aa: aav
+    ab: abv
+  - b: bv
+    ba: bav
+    bb: bbv
+
+'''
+
         tmp = [
             [ cls._simple_map, cls._simple_map_data ],
             [ cls._simple_seq, cls._simple_seq_data ],
-            [ cls._nested, cls._nested_data ]
+            [ cls._nested, cls._nested_data ],
+            [ cls._mixed, cls._mixed_data ],
         ]
 
         for f, d in tmp:
@@ -75,6 +89,7 @@ root:
             cls._simple_map,
             cls._simple_seq,
             cls._nested,
+            cls._mixed,
         ]
 
         for f in tmp:
@@ -87,12 +102,12 @@ root:
     def testSimpleYamlContent(self):
         """Validate Yaml content readers."""
 
-        def _build_node_desc(node, left):
+        def _build_node_desc(node, left, extra = ''):
 
             line = node.yaml_line
 
             if line:
-                prefix = '- ' if line.is_list_item else ''
+                prefix = '- ' if line.is_list_item else extra
                 desc = left + prefix + line.key + ':' + (' ' + line.value if line.value else '') + '\n'
                 indent = '  '
             else:
@@ -100,8 +115,12 @@ root:
                 indent = ''
 
             if node.collection:
+
+                if node.collection.is_sequence:
+                    extra = '  '
+
                 for child in node.collection.nodes:
-                    desc += _build_node_desc(child, left + indent)
+                    desc += _build_node_desc(child, left + indent, extra)
 
             return desc
 
@@ -130,6 +149,14 @@ root:
 
         self.assertEqual('\n' + fulldesc + '\n', self._nested_data.decode('ascii'))
 
+        reader = YamlReader.new_from_path(self._mixed.name)
+        self.assertIsNotNone(reader)
+        self.assertIsNotNone(reader.tree)
+
+        fulldesc = _build_node_desc(reader.tree.root, '')
+
+        self.assertEqual('\n' + fulldesc + '\n', self._mixed_data.decode('ascii'))
+
 
     def testSimpleYamlContentFinder(self):
         """Validate Yaml nested content search."""
@@ -194,3 +221,31 @@ root:
 
                 self.assertEqual(found[0].yaml_line.key, 'i')
                 self.assertEqual(found[0].yaml_line.is_list_item, True)
+
+
+    def testMixedYamlContentFinder(self):
+        """Validate Yaml mixed content search."""
+
+        reader = YamlReader.new_from_path(self._mixed.name)
+        self.assertIsNotNone(reader)
+
+        found = reader.tree.find_by_path('/root')
+
+        self.assertEqual(len(found), 1)
+
+        if len(found) == 1:
+            self.assertEqual(found[0].yaml_line.key, 'root')
+
+        found = reader.tree.find_by_path('/root/')
+
+        self.assertEqual(len(found), 2)
+
+        if len(found) == 2:
+
+            sub = found[0].find_by_path('/a')
+            self.assertEqual(len(sub), 1)
+            self.assertEqual(sub[0].yaml_line.key, 'a')
+
+            sub = found[0].find_by_path('/aa')
+            self.assertEqual(len(sub), 1)
+            self.assertEqual(sub[0].yaml_line.key, 'aa')
-- 
cgit v0.11.2-87-g4458