<commit_before>/*
  Copyright (c) 2015 <NAME> <<EMAIL>>

  This software is provided 'as-is', without any express or implied
  warranty. In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

     1. The origin of this software must not be misrepresented; you must
        not claim that you wrote the original software. If you use this
        software in a product, an acknowledgment in the product
        documentation would be appreciated but is not required.

     2. Altered source versions must be plainly marked as such, and must
        not be misrepresented as being the original software.

     3. This notice may not be removed or altered from any source
        distribution.
*/

/**
  @file search-tree.c Tests loading search trees from config files.
*/

#include "search-tree.h"

#include "test.h"
#include "string-utils.h"
#include "error-handling.h"

/** Counts the subnodes of the given node.

  @param parent_node The node containing the subnodes.

  @return The amount of subnodes in the given node.
*/
static size_t countSubnodes(SearchNode *parent_node)
{
  size_t counter = 0;

  for(SearchNode *node = parent_node->subnodes;
      node != NULL; node = node->next)
  {
    counter++;
  }

  return counter;
}

/** Returns the subnode with the given string as its name. It will
  terminate the test suite with failure if the node does not exist.

  @param parent_node The node containing the subnodes which should be
  searched.
  @param string The name of the node to search for.

  @return A valid search node.
*/
static SearchNode *findSubnode(SearchNode *parent_node, const char *string)
{
  String node_name = str(string);
  for(SearchNode *node = parent_node->subnodes;
      node != NULL; node = node->next)
  {
    if(strCompare(node->name, node_name))
    {
      return node;
    }
  }

  die("failed to find node with name \"%s\"", string);

  /* Some compilers are not aware that die() never returns. */
  return NULL;
}

/** Counts all ignore expressions that the given SearchNode contains.

  @param node The SearchNode containing the ignore expression list.

  @return The amount of ignore expressions in the given nodes ignore
  expression list.
*/
static size_t countIgnoreExpressions(SearchNode *node)
{
  size_t counter = 0;

  for(RegexList *expression = *node->ignore_expressions;
      expression != NULL; expression = expression->next)
  {
    counter++;
  }

  return counter;
}

/** Checks if a valid ignore expression with the given properties exists in
  the given SearchNode.

  @param node The node containing the ignore expression list.
  @param pattern The pattern which should be searched for.
  @param line_nr The number of the line in the config file, on which the
  given pattern was defined initially.

  @return True, if a pattern with the specified properties exists in the
  ignore expression list.
*/
static bool ignoreExpressionExists(SearchNode *node, const char *pattern,
                                   size_t line_nr)
{
  String expression_string = str(pattern);
  for(RegexList *expression = *node->ignore_expressions;
      expression != NULL; expression = expression->next)
  {
    if(expression->has_matched == false &&
       expression->line_nr == line_nr &&
       strCompare(expression->expression, expression_string))
    {
      return true;
    }
  }

  return false;
}

static void checkBasicNode(SearchNode *node, const char *name,
                           size_t line_nr, bool has_regex,
                           BackupPolicy policy, bool policy_inherited,
                           size_t policy_line_nr, size_t subnode_count,
                           bool subnodes_contain_regex)
{
  assert_true(node != NULL);

  assert_true(strCompare(node->name, str(name)));
  assert_true(node->line_nr == line_nr);

  if(has_regex)
  {
    assert_true(node->regex != NULL);
  }
  else
  {
    assert_true(node->regex == NULL);
  }

  assert_true(node->policy == policy);
  assert_true(node->policy_inherited == policy_inherited);
  assert_true(node->policy_line_nr == policy_line_nr);

  assert_true(countSubnodes(node) == subnode_count);
  if(node->subnodes == NULL)
  {
    assert_true(subnode_count == 0);
    assert_true(subnodes_contain_regex == false);
    assert_true(node->subnodes_contain_regex == false);
  }
  else
  {
    assert_true(node->subnodes_contain_regex == subnodes_contain_regex);
  }

  assert_true(node->ignore_expressions != NULL);
}

/** Extends checkBasicNode() with root node specific checks by wrapping it.
*/
static void checkRootNode(SearchNode *node, BackupPolicy policy,
                          size_t policy_line_nr, size_t subnode_count,
                          bool subnodes_contain_regex,
                          size_t ignore_expression_count)
{
  checkBasicNode(node, "/", 0, false, policy, false, policy_line_nr,
                 subnode_count, subnodes_contain_regex);

  assert_true(countIgnoreExpressions(node) == ignore_expression_count);
  assert_true(node->next == NULL);
}

static void checkNode(SearchNode *node, SearchNode *root_node,
                      const char *name, size_t line_nr, bool has_regex,
                      BackupPolicy policy, bool policy_inherited,
                      size_t policy_line_nr, size_t subnode_count,
                      bool subnodes_contain_regex)
{
  checkBasicNode(node, name, line_nr, has_regex, policy, policy_inherited,
                 policy_line_nr, subnode_count, subnodes_contain_regex);

  assert_true(node->ignore_expressions == root_node->ignore_expressions);
}

/** Loads a search tree from a simple config file and checks it.

  @param path A null-terminated string, containing a path to a valid config
  file.<commit_msg>Added missing documentation to search tree test<commit_after>/*
  Copyright (c) 2015 <NAME> <<EMAIL>>

  This software is provided 'as-is', without any express or implied
  warranty. In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

     1. The origin of this software must not be misrepresented; you must
        not claim that you wrote the original software. If you use this
        software in a product, an acknowledgment in the product
        documentation would be appreciated but is not required.

     2. Altered source versions must be plainly marked as such, and must
        not be misrepresented as being the original software.

     3. This notice may not be removed or altered from any source
        distribution.
*/

/**
  @file search-tree.c Tests loading search trees from config files.
*/

#include "search-tree.h"

#include "test.h"
#include "string-utils.h"
#include "error-handling.h"

/** Counts the subnodes of the given node.

  @param parent_node The node containing the subnodes.

  @return The amount of subnodes in the given node.
*/
static size_t countSubnodes(SearchNode *parent_node)
{
  size_t counter = 0;

  for(SearchNode *node = parent_node->subnodes;
      node != NULL; node = node->next)
  {
    counter++;
  }

  return counter;
}

/** Returns the subnode with the given string as its name. It will
  terminate the test suite with failure if the node does not exist.

  @param parent_node The node containing the subnodes which should be
  searched.
  @param string The name of the node to search for.

  @return A valid search node.
*/
static SearchNode *findSubnode(SearchNode *parent_node, const char *string)
{
  String node_name = str(string);
  for(SearchNode *node = parent_node->subnodes;
      node != NULL; node = node->next)
  {
    if(strCompare(node->name, node_name))
    {
      return node;
    }
  }

  die("failed to find node with name \"%s\"", string);

  /* Some compilers are not aware that die() never returns. */
  return NULL;
}

/** Counts all ignore expressions that the given SearchNode contains.

  @param node The SearchNode containing the ignore expression list.

  @return The amount of ignore expressions in the given nodes ignore
  expression list.
*/
static size_t countIgnoreExpressions(SearchNode *node)
{
  size_t counter = 0;

  for(RegexList *expression = *node->ignore_expressions;
      expression != NULL; expression = expression->next)
  {
    counter++;
  }

  return counter;
}

/** Checks if a valid ignore expression with the given properties exists in
  the given SearchNode.

  @param node The node containing the ignore expression list.
  @param pattern The pattern which should be searched for.
  @param line_nr The number of the line in the config file, on which the
  given pattern was defined initially.

  @return True, if a pattern with the specified properties exists in the
  ignore expression list.
*/
static bool ignoreExpressionExists(SearchNode *node, const char *pattern,
                                   size_t line_nr)
{
  String expression_string = str(pattern);
  for(RegexList *expression = *node->ignore_expressions;
      expression != NULL; expression = expression->next)
  {
    if(expression->has_matched == false &&
       expression->line_nr == line_nr &&
       strCompare(expression->expression, expression_string))
    {
      return true;
    }
  }

  return false;
}

/** Checks if the given node contains the given values.

  @param node The node that should be checked.
  @param name The name of the node.
  @param line_nr The number of the line, on which the node was initially
  defined in the config file.
  @param has_regex True, if the node must have a compiled regex.
  @param policy The policy of the node.
  @param policy_inherited True, if the node has inherited its policy.
  @param policy_line_nr The number of the line in the config file on which
  the node has got its policy assigned to it.
  @param subnode_count The amount of subnodes in the node.
  @param subnodes_contain_regex True, if at least one subnode contains a
  regex.
*/
static void checkBasicNode(SearchNode *node, const char *name,
                           size_t line_nr, bool has_regex,
                           BackupPolicy policy, bool policy_inherited,
                           size_t policy_line_nr, size_t subnode_count,
                           bool subnodes_contain_regex)
{
  assert_true(node != NULL);

  assert_true(strCompare(node->name, str(name)));
  assert_true(node->line_nr == line_nr);

  if(has_regex)
  {
    assert_true(node->regex != NULL);
  }
  else
  {
    assert_true(node->regex == NULL);
  }

  assert_true(node->policy == policy);
  assert_true(node->policy_inherited == policy_inherited);
  assert_true(node->policy_line_nr == policy_line_nr);

  assert_true(countSubnodes(node) == subnode_count);
  if(node->subnodes == NULL)
  {
    assert_true(subnode_count == 0);
    assert_true(subnodes_contain_regex == false);
    assert_true(node->subnodes_contain_regex == false);
  }
  else
  {
    assert_true(node->subnodes_contain_regex == subnodes_contain_regex);
  }

  assert_true(node->ignore_expressions != NULL);
}

/** Extends checkBasicNode() with root node specific checks by wrapping it.
*/
static void checkRootNode(SearchNode *node, BackupPolicy policy,
                          size_t policy_line_nr, size_t subnode_count,
                          bool subnodes_contain_regex,
                          size_t ignore_expression_count)
{
  checkBasicNode(node, "/", 0, false, policy, false, policy_line_nr,
                 subnode_count, subnodes_contain_regex);

  assert_true(countIgnoreExpressions(node) == ignore_expression_count);
  assert_true(node->next == NULL);
}

/** Extends checkBasicNode() with some additional checks by wrapping it.
  Here are the added parameters:

  @param root_node The root node of the tree, to which the given node
  belongs.
*/
static void checkNode(SearchNode *node, SearchNode *root_node,
                      const char *name, size_t line_nr, bool has_regex,
                      BackupPolicy policy, bool policy_inherited,
                      size_t policy_line_nr, size_t subnode_count,
                      bool subnodes_contain_regex)
{
  checkBasicNode(node, name, line_nr, has_regex, policy, policy_inherited,
                 policy_line_nr, subnode_count, subnodes_contain_regex);

  assert_true(node->ignore_expressions == root_node->ignore_expressions);
}

/** Loads a search tree from a simple config file and checks it.

  @param path A null-terminated string, containing a path to a valid config
  file.
{'fraction_non_alphanumeric': 0.07905816310619056, 'fraction_numerical': 0.0017152658662092624, 'mean_word_length': 3.1578606158833065, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1260010', 'n_tokens_mistral': 3654, 'n_tokens_neox': 3553, 'n_words': 1301}