/*
 * Author: Joshua Brindle <jbrindle@tresys.com>
 *         Chad Sellers <csellers@tresys.com>
 *         Chris PeBenito <cpebenito@tresys.com>
 *
 * Copyright (C) 2006 Tresys Technology, LLC
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

/* This has tests that are common between test suites*/

#include <sepol/policydb/avrule_block.h>

#include <CUnit/Basic.h>

void test_sym_presence(policydb_t * p, char *id, int sym_type, unsigned int scope_type, unsigned int *decls, unsigned int len)
{
	scope_datum_t *scope;
	int found;
	unsigned int i, j;
	/* make sure it is in global symtab */
	if (!hashtab_search(p->symtab[sym_type].table, id)) {
		fprintf(stderr, "symbol %s not found in table %d\n", id, sym_type);
		CU_FAIL_FATAL();
	}
	/* make sure its scope is correct */
	scope = hashtab_search(p->scope[sym_type].table, id);
	CU_ASSERT_FATAL(scope != NULL);
	CU_ASSERT(scope->scope == scope_type);
	CU_ASSERT(scope->decl_ids_len == len);
	if (scope->decl_ids_len != len)
		fprintf(stderr, "sym %s has %d decls, %d expected\n", id, scope->decl_ids_len, len);
	for (i = 0; i < len; i++) {
		found = 0;
		for (j = 0; j < len; j++) {
			if (decls[i] == scope->decl_ids[j])
				found++;
		}
		CU_ASSERT(found == 1);
	}

}

static int common_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data)
{
	common_datum_t *d = (common_datum_t *) datum;
	policydb_t *p = (policydb_t *) data;

	CU_ASSERT(p->sym_val_to_name[SYM_COMMONS][d->s.value - 1] == (char *)key);
	return 0;
}

static int class_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data)
{
	class_datum_t *d = (class_datum_t *) datum;
	policydb_t *p = (policydb_t *) data;

	CU_ASSERT(p->sym_val_to_name[SYM_CLASSES][d->s.value - 1] == (char *)key);
	CU_ASSERT(p->class_val_to_struct[d->s.value - 1] == d);
	return 0;
}

static int role_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data)
{
	role_datum_t *d = (role_datum_t *) datum;
	policydb_t *p = (policydb_t *) data;

	CU_ASSERT(p->sym_val_to_name[SYM_ROLES][d->s.value - 1] == (char *)key);
	CU_ASSERT(p->role_val_to_struct[d->s.value - 1] == d);
	return 0;
}

static int type_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data)
{
	type_datum_t *d = (type_datum_t *) datum;
	policydb_t *p = (policydb_t *) data;

	if (!d->primary)
		return 0;

	CU_ASSERT(p->sym_val_to_name[SYM_TYPES][d->s.value - 1] == (char *)key);
	CU_ASSERT(p->type_val_to_struct[d->s.value - 1] == d);

	return 0;
}

static int user_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data)
{
	user_datum_t *d = (user_datum_t *) datum;
	policydb_t *p = (policydb_t *) data;

	CU_ASSERT(p->sym_val_to_name[SYM_USERS][d->s.value - 1] == (char *)key);
	CU_ASSERT(p->user_val_to_struct[d->s.value - 1] == d);
	return 0;
}

static int cond_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data)
{
	cond_bool_datum_t *d = (cond_bool_datum_t *) datum;
	policydb_t *p = (policydb_t *) data;

	CU_ASSERT(p->sym_val_to_name[SYM_BOOLS][d->s.value - 1] == (char *)key);
	CU_ASSERT(p->bool_val_to_struct[d->s.value - 1] == d);
	return 0;
}

static int level_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data)
{
	level_datum_t *d = (level_datum_t *) datum;
	policydb_t *p = (policydb_t *) data;

	CU_ASSERT(p->sym_val_to_name[SYM_LEVELS][d->level->sens - 1] == (char *)key);
	return 0;
}

static int cat_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data)
{
	cat_datum_t *d = (cat_datum_t *) datum;
	policydb_t *p = (policydb_t *) data;

	CU_ASSERT(p->sym_val_to_name[SYM_CATS][d->s.value - 1] == (char *)key);
	return 0;
}

static int (*test_index_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *p) = {
common_test_index, class_test_index, role_test_index, type_test_index, user_test_index, cond_test_index, level_test_index, cat_test_index,};

void test_policydb_indexes(policydb_t * p)
{
	int i;

	for (i = 0; i < SYM_NUM; i++) {
		hashtab_map(p->symtab[i].table, test_index_f[i], p);
	}
}

void test_alias_datum(policydb_t * p, char *id, char *primary_id, char mode, unsigned int flavor)
{
	type_datum_t *type, *primary;
	unsigned int my_primary, my_flavor, my_value;

	type = hashtab_search(p->p_types.table, id);
	primary = hashtab_search(p->p_types.table, primary_id);

	CU_ASSERT_PTR_NOT_NULL(type);
	CU_ASSERT_PTR_NOT_NULL(primary);

	if (type && primary) {
		if (mode) {
			my_flavor = type->flavor;
		} else {
			my_flavor = flavor;
		}

		if (my_flavor == TYPE_TYPE) {
			my_primary = 0;
			my_value = primary->s.value;
		} else if (my_flavor == TYPE_ALIAS) {
			my_primary = primary->s.value;
			CU_ASSERT_NOT_EQUAL(type->s.value, primary->s.value);
			my_value = type->s.value;
		} else {
			CU_FAIL("not an alias");
		}

		CU_ASSERT(type->primary == my_primary);
		CU_ASSERT(type->flavor == my_flavor);
		CU_ASSERT(type->s.value == my_value);
	}
}

role_datum_t *test_role_type_set(policydb_t * p, char *id, avrule_decl_t * decl, char **types, unsigned int len, unsigned int flags)
{
	ebitmap_node_t *tnode;
	unsigned int i, j, new, found = 0;
	role_datum_t *role;

	if (decl)
		role = hashtab_search(decl->p_roles.table, id);
	else
		role = hashtab_search(p->p_roles.table, id);

	if (!role)
		printf("role %s can't be found! \n", id);

	CU_ASSERT_FATAL(role != NULL);

	ebitmap_for_each_bit(&role->types.types, tnode, i) {
		if (ebitmap_node_get_bit(tnode, i)) {
			new = 0;
			for (j = 0; j < len; j++) {
				if (strcmp(p->sym_val_to_name[SYM_TYPES][i], types[j]) == 0) {
					found++;
					new = 1;
				}
			}
			if (new == 0) {
				printf("\nRole %s had type %s not in types array\n", id, p->sym_val_to_name[SYM_TYPES][i]);
			}
			CU_ASSERT(new == 1);
		}
	}
	CU_ASSERT(found == len);
	if (found != len)
		printf("\nrole %s has %d types, %d expected\n", p->sym_val_to_name[SYM_ROLES][role->s.value - 1], found, len);
	/* roles should never have anything in the negset */
	CU_ASSERT(role->types.negset.highbit == 0);
	CU_ASSERT(role->types.flags == flags);

	return role;
}

void test_attr_types(policydb_t * p, char *id, avrule_decl_t * decl, char **types, int len)
{
	ebitmap_node_t *tnode;
	int j, new, found = 0;
	unsigned int i;
	type_datum_t *attr;

	if (decl)
		attr = hashtab_search(decl->p_types.table, id);
	else
		attr = hashtab_search(p->p_types.table, id);

	if (attr == NULL)
		printf("could not find attr %s in decl %d\n", id, decl->decl_id);
	CU_ASSERT_FATAL(attr != NULL);
	CU_ASSERT(attr->flavor == TYPE_ATTRIB);
	CU_ASSERT(attr->primary == 1);

	ebitmap_for_each_bit(&attr->types, tnode, i) {
		if (ebitmap_node_get_bit(tnode, i)) {
			new = 0;
			for (j = 0; j < len; j++) {
				if (strcmp(p->sym_val_to_name[SYM_TYPES][i], types[j]) == 0) {
					found++;
					new = 1;
				}
			}
			if (new == 0) {
				printf("\nattr %s had type %s not in types array\n", id, p->sym_val_to_name[SYM_TYPES][i]);
			}
			CU_ASSERT(new == 1);
		}
	}
	CU_ASSERT(found == len);
	if (found != len)
		printf("\nattr %s has %d types, %d expected\n", id, found, len);
}
