--- /dev/null
- attrs->loa_atime_ms = value;
+/*
+ * Copyright (c) 2019, DDN Storage Corporation.
+ */
+/*
+ *
+ * Unit test for policy evalution core
+ *
+ * Author: Li Xi <lixi@ddn.com>
+ */
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include "debug.h"
+#include "lipe_object_attrs.h"
+#include "policy.h"
+
+enum {
+ /* Success */
+ RETVAL_SUCCESS = 0,
+ /* Help message without any other operation */
+ RETVAL_HELP = 1,
+ /* The argument to this program is invalid */
+ RETVAL_ARG_INVALID = 2,
+ /* The attribute name is invalid */
+ RETVAL_ATTR_NAME_INVALID = 3,
+ /* The attribute value is invalid */
+ RETVAL_ATTR_VALUE_INVALID = 4,
+ /* The expression is invalid */
+ RETVAL_EXPRESSION_INVALID = 5,
+ /* The expression value is not expected */
+ RETVAL_UNEXPECTED_VALUE = 6,
+ /* Unexpected internal error */
+ RETVAL_INTERNAL_ERROR = 7,
+ /* Attribute has no value */
+ RETVAL_ATTR_NO_VALUE = 8,
+};
+
+static void usage(char *prog)
+{
+ fprintf(stderr,
+ "Usage: %s [--$ATTR $VALUE]... [--dont-evaluate] expression [expected_value]\n",
+ prog);
+}
+
+static int set_attribute_value(enum lipe_policy_attribute_type type,
+ struct lipe_object_attrs *attrs,
+ int64_t value)
+{
+ int rc = 0;
+ struct hsm_user_state *hsm_state = &attrs->loa_hsm_state;
+
+ switch (type) {
+ default:
+ LBUG();
+ case LIPE_POLICY_ATTRIBUTE_ATIME:
+ attrs->loa_atime_ms = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_MTIME:
++ attrs->loa_mtime_ms = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_CTIME:
+ attrs->loa_ctime_ms = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_INUM:
+ attrs->loa_ino = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_SIZE:
+ attrs->loa_size = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_MODE:
+ attrs->loa_mode = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_UID:
+ attrs->loa_uid = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_GID:
+ attrs->loa_gid = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_BLOCKS:
+ attrs->loa_blocks = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_TYPE:
+ attrs->loa_mode &= ~S_IFMT;
+ attrs->loa_mode |= value & S_IFMT;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_FLAGS:
+ attrs->loa_flags = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_NLINK:
+ attrs->loa_nlinks = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_HSM_STATES:
+ hsm_state->hus_states = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_STRIPE_COUNT:
+ attrs->loa_stripe_count = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_STRIPE_SIZE:
+ attrs->loa_stripe_size = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_COMP_COUNT:
+ attrs->loa_comp_count = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_ENTRIES:
+ attrs->loa_entries = value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_EMPTY:
+ attrs->loa_is_empty = (bool)value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_NOGROUP:
+ attrs->loa_nogroup = (bool)value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_NOUSER:
+ attrs->loa_nouser = (bool)value;
+ break;
+ case LIPE_POLICY_ATTRIBUTE_PROJID:
+ attrs->loa_projid = value;
+ break;
+ }
+ return rc;
+}
+
+static int set_sysattr_value(enum lipe_policy_sysattr_type type,
+ struct lipe_policy_sysattrs *sysattrs,
+ int64_t value)
+{
+ switch (type) {
+ default:
+ LBUG();
+ case LIPE_POLICY_SYSATTR_TIME:
+ sysattrs->lps_sys_time = value;
+ break;
+ }
+ return 0;
+}
+
+static int parse_attr_pair(const char *attr_name,
+ const char *attr_value,
+ struct lipe_object_attrs *attrs,
+ struct lipe_policy_sysattrs *sysattrs)
+{
+ int rc;
+ enum lipe_policy_sysattr_type sys_type;
+ enum lipe_policy_attribute_type type;
+ int64_t value;
+ char *endptr;
+ __u64 attr_bits;
+ bool is_attr = false;
+
+ rc = lipe_policy_attr_parse(attr_name, &type, &attr_bits);
+ if (rc) {
+ rc = lipe_policy_sys_attr_parse(attr_name, &sys_type);
+ if (rc) {
+ LERROR("failed to parse attr name [%s]\n", attr_name);
+ return RETVAL_ATTR_NAME_INVALID;
+ }
+ } else {
+ is_attr = true;
+ }
+
+ value = strtoll(attr_value, &endptr, 0);
+ if (*endptr) {
+ LERROR("value [%s] is not valid\n", attr_value);
+ return RETVAL_ATTR_VALUE_INVALID;
+ }
+
+ if ((value == LLONG_MAX || value == LLONG_MIN) &&
+ errno == ERANGE) {
+ LERROR("number [%s] overflows\n", attr_value);
+ return RETVAL_ATTR_VALUE_INVALID;
+ }
+
+ if (is_attr) {
+ attrs->loa_attr_bits |= attr_bits;
+ rc = set_attribute_value(type, attrs, value);
+ if (rc)
+ return RETVAL_ATTR_VALUE_INVALID;
+ } else {
+ sysattrs->lps_attr_bits |= attr_bits;
+ rc = set_sysattr_value(sys_type, sysattrs, value);
+ if (rc)
+ return RETVAL_ATTR_VALUE_INVALID;
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+ int rc;
+ char *value;
+ char *option;
+ int option_length;
+ bool dont_evaluate = false;
+ int64_t result;
+ struct lipe_rule *rule;
+ char result_string[1024];
+ struct lipe_policy policy;
+ const char *expected_result = "no_evaluation";
+ const char *string_expression;
+ struct lipe_rule_group *group;
+ struct lipe_object_attrs attrs;
+ struct lipe_policy_sysattrs sysattrs;
+ const char *group_name = "group_name";
+ const char *string_argument = "counter_name";
+ const char *string_action = lipe_action_names[LAT_COUNTER_INC];
+
+ lipe_object_attrs_init(&attrs);
+ attrs.loa_attr_bits = 0;
+ sysattrs.lps_attr_bits = 0;
+
+ for (i = 1; i < argc; i++) {
+ option = argv[i];
+ option_length = strlen(option);
+ if (option_length < 2)
+ break;
+ if (option[0] != '-')
+ break;
+ if (option_length == 2) {
+ if (option[1] == 'h') {
+ usage(argv[0]);
+ exit(RETVAL_HELP);
+ } else {
+ break;
+ }
+ }
+
+ if (option[1] != '-')
+ break;
+ option = &option[2];
+ if (strcmp(option, "dont-evaluate") == 0) {
+ dont_evaluate = true;
+ continue;
+ } else if (strcmp(option, "help") == 0) {
+ usage(argv[0]);
+ exit(RETVAL_HELP);
+ } else {
+ if (i == argc - 1) {
+ LERROR("no value for attribute [%s]\n",
+ option);
+ exit(RETVAL_ARG_INVALID);
+ }
+ i++;
+ value = argv[i];
+ /* might be pair of attr and value */
+ rc = parse_attr_pair(option, value, &attrs, &sysattrs);
+ if (rc)
+ exit(rc);
+ }
+ }
+
+ if (i == argc) {
+ LERROR("no argument for expression\n");
+ return RETVAL_ARG_INVALID;
+ }
+
+ string_expression = argv[i];
+ if (!dont_evaluate) {
+ i++;
+ if (i == argc) {
+ LERROR("no argument for expected_argument\n");
+ return RETVAL_ARG_INVALID;
+ }
+ expected_result = argv[i];
+ }
+
+ rc = lipe_policy_init(&policy);
+ if (rc) {
+ LERROR("failed to init policy\n");
+ return RETVAL_INTERNAL_ERROR;
+ }
+
+ group = lipe_rule_group_add(&policy, group_name);
+ if (group == NULL) {
+ LERROR("failed to add group\n");
+ rc = RETVAL_INTERNAL_ERROR;
+ goto out;
+ }
+
+ rc = lipe_rule_add(&policy, group, string_expression,
+ string_action, string_argument, string_argument);
+ if (rc) {
+ LERROR("invalid expression [%s]\n", string_expression);
+ rc = RETVAL_EXPRESSION_INVALID;
+ goto out;
+ }
+
+ lipe_list_for_each_entry(rule, &group->lrg_rules, lr_linkage) {
+ if (dont_evaluate)
+ continue;
+
+ if ((rule->lr_attr_bits & (~attrs.loa_attr_bits)) != 0) {
+ LERROR("dosnot have expected attr bits, expected [%llx] got [%llx]\n",
+ rule->lr_attr_bits, attrs.loa_attr_bits);
+ rc = RETVAL_ATTR_NO_VALUE;
+ goto out;
+ }
+
+ rc = lipe_rule_evaluate(rule, &attrs, &sysattrs,
+ &result);
+ if (rc) {
+ rc = RETVAL_INTERNAL_ERROR;
+ goto out;
+ }
+
+ snprintf(result_string, sizeof(result_string), "%"PRId64,
+ result);
+ if (strcmp(result_string, expected_result) != 0) {
+ LERROR("expected result [%s], got [%s]\n",
+ expected_result, result_string);
+ rc = RETVAL_UNEXPECTED_VALUE;
+ goto out;
+ }
+ }
+out:
+ lipe_policy_fini(&policy);
+ return rc;
+}