/* kim/test/test_kim_identity.c */
/*
 * Copyright 2006 Massachusetts Institute of Technology.
 * All Rights Reserved.
 *
 * Export of this software from the United States of America may
 * require a specific license from the United States Government.
 * It is the responsibility of any person or organization contemplating
 * export to obtain such a license before exporting.
 *
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
 * distribute this software and its documentation for any purpose and
 * without fee is hereby granted, provided that the above copyright
 * notice appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation, and that
 * the name of M.I.T. not be used in advertising or publicity pertaining
 * to distribution of the software without specific, written prior
 * permission.  Furthermore if you modify this software you must label
 * your software as modified software and not distribute it in such a
 * fashion that it might be confused with the original M.I.T. software.
 * M.I.T. makes no representations about the suitability of
 * this software for any purpose.  It is provided "as is" without express
 * or implied warranty.
 */

#include "test_kim_identity.h"

typedef struct test_identity_d {
    const char *string;
    const char *display_string;
    kim_boolean is_tgt_service;
    const char *realm;
    kim_count component_count;
    const char *components[5];
} test_identity;


test_identity test_identities[] = {
    {"a@B",                            "a@B",                            0, "B",           1, { "a",              NULL,          NULL, NULL, NULL } },
    {"user@EXAMPLE.COM",               "user@EXAMPLE.COM",               0, "EXAMPLE.COM", 1, { "user",           NULL,          NULL, NULL, NULL } },
    {"krbtgt@EXAMPLE.COM",             "krbtgt@EXAMPLE.COM",             0, "EXAMPLE.COM", 1, { "krbtgt",         NULL,          NULL, NULL, NULL } },
    {"krbtgt/EXAMPLE.COM@EXAMPLE.COM", "krbtgt/EXAMPLE.COM@EXAMPLE.COM", 1, "EXAMPLE.COM", 2, { "krbtgt",         "EXAMPLE.COM", NULL, NULL, NULL } },
    {"krbtgt/OTHER.COM@EXAMPLE.COM",   "krbtgt/OTHER.COM@EXAMPLE.COM",   1, "EXAMPLE.COM", 2, { "krbtgt",         "OTHER.COM",   NULL, NULL, NULL } },
    {"a space@EXAMPLE.COM",            "a space@EXAMPLE.COM",            0, "EXAMPLE.COM", 1, { "a space",        NULL,          NULL, NULL, NULL } },
    {"üñîçödé@EXAMPLE.COM",            "üñîçödé@EXAMPLE.COM",            0, "EXAMPLE.COM", 1, { "üñîçödé",        NULL,          NULL, NULL, NULL } },
    {"user.name@EXAMPLE.COM",          "user.name@EXAMPLE.COM",          0, "EXAMPLE.COM", 1, { "user.name",      NULL,          NULL, NULL, NULL } },
    {"user\\/instance@EXAMPLE.COM",    "user/instance@EXAMPLE.COM",      0, "EXAMPLE.COM", 1, { "user\/instance", NULL,          NULL, NULL, NULL } },
    {"user\\@instance@EXAMPLE.COM",    "user@instance@EXAMPLE.COM",      0, "EXAMPLE.COM", 1, { "user\@instance", NULL,          NULL, NULL, NULL } },
    {"user/instance@EXAMPLE.COM",      "user/instance@EXAMPLE.COM",      0, "EXAMPLE.COM", 2, { "user",           "instance",    NULL, NULL, NULL } },
    {"user/i1/i2@EXAMPLE.COM",         "user/i1/i2@EXAMPLE.COM",         0, "EXAMPLE.COM", 3, { "user",           "i1",          "i2", NULL, NULL } },
    {"user/i1/i2/i3/i4@EXAMPLE.COM",   "user/i1/i2/i3/i4@EXAMPLE.COM",   0, "EXAMPLE.COM", 5, { "user",           "i1",          "i2", "i3", "i4" } },
    {"an insanely long principal for testing icky hex key principals/an insanely long instance for testing icky hex key principals@AN-INSANELY-LONG-REALM-NAME-FOR-TESTING-AUTOGENERATED-REALM-NAMES",
     "an insanely long principal for testing icky hex key principals/an insanely long instance for testing icky hex key principals@AN-INSANELY-LONG-REALM-NAME-FOR-TESTING-AUTOGENERATED-REALM-NAMES",
     0, "AN-INSANELY-LONG-REALM-NAME-FOR-TESTING-AUTOGENERATED-REALM-NAMES",
     2, { "an insanely long principal for testing icky hex key principals", "an insanely long instance for testing icky hex key principals", NULL, NULL, NULL } },
    { NULL, NULL, 0, NULL, 0, { NULL, NULL, NULL, NULL, NULL } },
};

/* ------------------------------------------------------------------------ */

void test_kim_identity_create_from_krb5_principal (kim_test_state_t state)
{
    kim_count i = 0;

    start_test (state, "kim_identity_create_from_krb5_principal");

    for (i = 0; test_identities[i].string; i++) {
        kim_error err = KIM_NO_ERROR;
        krb5_context context = NULL;
        krb5_principal principal = NULL;
        kim_identity identity = NULL;
        kim_string string = NULL;

        printf (".");

        err = krb5_init_context (&context);
        fail_if_error (state, "krb5_init_context", err,
                       "while initializing context");

        if (!err) {
            err = krb5_parse_name (context, test_identities[i].string, &principal);
            fail_if_error (state, "krb5_parse_name", err,
                           "while creating krb5_principal for %s",
                           test_identities[i].string);
        }

        if (!err) {
            err = kim_identity_create_from_krb5_principal (&identity, context, principal);
            fail_if_error (state, "kim_identity_create_from_string", err,
                           "while creating the identity for %s",
                           test_identities[i].string);
        }

        if (!err) {
            err = kim_identity_get_string (identity, &string);
            fail_if_error (state, "kim_identity_get_string", err,
                           "while getting the string for %s",
                           test_identities[i].string);
        }

        if (!err && strcmp (string, test_identities[i].string)) {
            log_failure (state, "Unexpected string (got '%s', expected '%s')",
                         string, test_identities[i].string);
        }

        kim_string_free (&string);
        kim_identity_free (&identity);
        if (principal) { krb5_free_principal (context, principal); }
        if (context  ) { krb5_free_context (context); }
    }

    printf ("\n");

    end_test (state);
}

/* ------------------------------------------------------------------------ */

void test_kim_identity_create_from_string (kim_test_state_t state)
{
    kim_count i = 0;

    start_test (state, "kim_identity_create_from_string");

    for (i = 0; test_identities[i].string; i++) {
        kim_error err = KIM_NO_ERROR;
        kim_identity identity = NULL;
        kim_string string = NULL;

        printf (".");

        if (!err) {
            err = kim_identity_create_from_string (&identity, test_identities[i].string);
            fail_if_error (state, "kim_identity_create_from_string", err,
                           "while creating the identity for %s",
                           test_identities[i].string);
        }

        if (!err) {
            err = kim_identity_get_string (identity, &string);
            fail_if_error (state, "kim_identity_get_string", err,
                           "while getting the string for %s",
                           test_identities[i].string);
        }

        if (!err && strcmp (string, test_identities[i].string)) {
            log_failure (state, "Unexpected string (got '%s', expected '%s')",
                         string, test_identities[i].string);
        }

        kim_string_free (&string);
        kim_identity_free (&identity);
    }

    printf ("\n");

    end_test (state);
}


/* ------------------------------------------------------------------------ */

void test_kim_identity_create_from_components (kim_test_state_t state)
{
    kim_count i = 0;

    start_test (state, "kim_identity_create_from_components");

    for (i = 0; test_identities[i].string; i++) {
        kim_error err = KIM_NO_ERROR;
        kim_identity identity = NULL;
        kim_string string = NULL;

        printf (".");

        if (!err) {
            err = kim_identity_create_from_components (&identity,
                                                       test_identities[i].realm,
                                                       test_identities[i].components[0],
                                                       test_identities[i].components[1],
                                                       test_identities[i].components[2],
                                                       test_identities[i].components[3],
                                                       test_identities[i].components[4],
                                                       NULL);
            fail_if_error (state, "kim_identity_create_from_components", err,
                           "while creating the identity for %s",
                           test_identities[i].string);
        }

        if (!err) {
            err = kim_identity_get_string (identity, &string);
            fail_if_error (state, "kim_identity_get_string", err,
                           "while getting the string for %s",
                           test_identities[i].string);
        }

        if (!err && strcmp (string, test_identities[i].string)) {
            log_failure (state, "Unexpected string (got '%s', expected '%s')",
                         string, test_identities[i].string);
        }

        kim_string_free (&string);
        kim_identity_free (&identity);
    }

    printf ("\n");

    end_test (state);
}

/* ------------------------------------------------------------------------ */

void test_kim_identity_copy (kim_test_state_t state)
{
    kim_count i = 0;

    start_test (state, "kim_identity_copy");

    for (i = 0; test_identities[i].string; i++) {
        kim_error err = KIM_NO_ERROR;
        kim_identity identity = NULL;
        kim_identity identity_copy = NULL;
        kim_string string = NULL;

        printf (".");

        if (!err) {
            err = kim_identity_create_from_string (&identity, test_identities[i].string);
            fail_if_error (state, "kim_identity_create_from_string", err,
                           "while creating the identity for %s",
                           test_identities[i].string);
        }

        if (!err) {
            err = kim_identity_copy (&identity_copy, identity);
            fail_if_error (state, "kim_identity_copy", err,
                           "while copying %s", test_identities[i].string);
        }

        if (!err) {
            err = kim_identity_get_string (identity_copy, &string);
            fail_if_error (state, "kim_identity_get_string", err,
                           "while getting the string for the copy of %s",
                           test_identities[i].string);
        }

        if (!err && strcmp (string, test_identities[i].string)) {
            log_failure (state, "Unexpected string (got '%s', expected '%s')",
                         string, test_identities[i].string);
        }

        kim_string_free (&string);
        kim_identity_free (&identity_copy);
        kim_identity_free (&identity);
    }

    printf ("\n");

    end_test (state);
}

/* ------------------------------------------------------------------------ */

void test_kim_identity_compare (kim_test_state_t state)
{
    kim_count i, j = 0;

    start_test (state, "kim_identity_create_from_string");

    for (i = 0; test_identities[i].string; i++) {
        kim_error err = KIM_NO_ERROR;
        kim_identity identity = NULL;

        printf (".");

        err = kim_identity_create_from_string (&identity, test_identities[i].string);
        fail_if_error (state, "kim_identity_create_from_string", err,
                       "while creating the identity for %s",
                       test_identities[i].string);

        for (j = 0; !err && test_identities[j].string; j++) {
            kim_identity compare_to_identity = NULL;
            kim_comparison comparison = 0;

            err = kim_identity_create_from_string (&compare_to_identity, test_identities[j].string);
            fail_if_error (state, "kim_identity_create_from_string", err,
                           "while creating the identity for %s",
                           test_identities[j].string);

            if (!err) {
                err = kim_identity_compare (identity, compare_to_identity, &comparison);
                fail_if_error (state, "kim_identity_compare", err,
                               "while comparing %s and %s",
                               test_identities[i].string, test_identities[j].string);
            }

            if (!err) {
                if (i == j && !kim_comparison_is_equal_to (comparison)) {
                    log_failure (state, "Expected %s and %s to be equal but kim_identity_compare returned %d",
                                 test_identities[i].string, test_identities[j].string, comparison);

                } else if (i != j && kim_comparison_is_equal_to (comparison)) {
                    log_failure (state, "Expected %s and %s to be NOT equal but kim_identity_compare returned %d",
                                 test_identities[i].string, test_identities[j].string, comparison);
                }
            }

            kim_identity_free (&compare_to_identity);
        }

        kim_identity_free (&identity);
    }

    printf ("\n");

    end_test (state);
}

/* ------------------------------------------------------------------------ */

void test_kim_identity_get_display_string (kim_test_state_t state)
{
    kim_count i = 0;

    start_test (state, "kim_identity_get_display_string");

    for (i = 0; test_identities[i].string; i++) {
        kim_error err = KIM_NO_ERROR;
        kim_identity identity = NULL;
        kim_string string = NULL;

        printf (".");

        if (!err) {
            err = kim_identity_create_from_string (&identity, test_identities[i].string);
            fail_if_error (state, "kim_identity_create_from_string", err,
                           "while creating the identity for %s",
                           test_identities[i].string);
        }

        if (!err) {
            err = kim_identity_get_display_string (identity, &string);
            fail_if_error (state, "kim_identity_get_display_string", err,
                           "while getting the display string for %s",
                           test_identities[i].string);
        }

        if (!err && strcmp (string, test_identities[i].display_string)) {
            log_failure (state, "Unexpected display string for %s (got '%s', expected '%s')",
                         test_identities[i].string, string, test_identities[i].display_string);
        }

        kim_string_free (&string);
        kim_identity_free (&identity);
    }

    printf ("\n");

    end_test (state);
}

/* ------------------------------------------------------------------------ */

void test_kim_identity_get_realm (kim_test_state_t state)
{
    kim_count i = 0;

    start_test (state, "kim_identity_get_realm");

    for (i = 0; test_identities[i].string; i++) {
        kim_error err = KIM_NO_ERROR;
        kim_identity identity = NULL;
        kim_string realm = NULL;

        printf (".");

        if (!err) {
            err = kim_identity_create_from_string (&identity, test_identities[i].string);
            fail_if_error (state, "kim_identity_create_from_string", err,
                           "while creating the identity for %s",
                           test_identities[i].string);
        }

        if (!err) {
            err = kim_identity_get_realm (identity, &realm);
            fail_if_error (state, "kim_identity_get_realm", err,
                           "while getting the realm for %s", test_identities[i].string);
        }

        if (!err && strcmp (realm, test_identities[i].realm)) {
            log_failure (state, "Unexpected realm string (got '%s', expected '%s')",
                         realm, test_identities[i].realm);
        }

        kim_string_free (&realm);
        kim_identity_free (&identity);
    }

    printf ("\n");

    end_test (state);
}

/* ------------------------------------------------------------------------ */

void test_kim_identity_get_number_of_components (kim_test_state_t state)
{
    kim_count i = 0;

    start_test (state, "kim_identity_get_number_of_components");

    for (i = 0; test_identities[i].string; i++) {
        kim_error err = KIM_NO_ERROR;
        kim_identity identity = NULL;
        kim_count count = 0;

        printf (".");

        if (!err) {
            err = kim_identity_create_from_string (&identity, test_identities[i].string);
            fail_if_error (state, "kim_identity_create_from_string", err,
                           "while creating the identity for %s",
                           test_identities[i].string);
        }

        if (!err) {
            err = kim_identity_get_number_of_components (identity, &count);
            fail_if_error (state, "kim_identity_get_number_of_components", err,
                           "while getting number of components of %s",
                           test_identities[i].string);
        }

        if (!err && (count != test_identities[i].component_count)) {
            log_failure (state, "Unexpected component count of %s (got %d, expected %d)",
                         test_identities[i].string, (int) count, (int) test_identities[i].component_count);
        }

        kim_identity_free (&identity);
    }

    printf ("\n");

    end_test (state);
}

/* ------------------------------------------------------------------------ */

void test_kim_identity_get_component_at_index (kim_test_state_t state)
{
    kim_count i = 0;

    start_test (state, "kim_identity_get_component_at_index");

    for (i = 0; test_identities[i].string; i++) {
        kim_error err = KIM_NO_ERROR;
        kim_identity identity = NULL;
        kim_count c = 0;

        printf (".");

        if (!err) {
            err = kim_identity_create_from_string (&identity, test_identities[i].string);
            fail_if_error (state, "kim_identity_create_from_string", err,
                           "while creating the identity for %s",
                           test_identities[i].string);
        }

        for (c = 0; !err && c < test_identities[i].component_count; c++) {
            kim_string component = NULL;

            err = kim_identity_get_component_at_index (identity, c, &component);
            fail_if_error (state, "kim_identity_get_component_at_index", err,
                           "while getting component %d of %s", (int) c,
                           test_identities[i].string);

            if (!err && strcmp (component, test_identities[i].components[c])) {
                log_failure (state, "Unexpected component %d of %s (got '%s', expected '%s')",
                             (int) c, test_identities[i].string,
                             component, test_identities[i].components[c]);
            }

            kim_string_free (&component);
        }

        kim_identity_free (&identity);
    }

    printf ("\n");

    end_test (state);
}

/* ------------------------------------------------------------------------ */

void test_kim_identity_get_krb5_principal (kim_test_state_t state)
{
    kim_count i = 0;

    start_test (state, "kim_identity_get_krb5_principal");

    for (i = 0; test_identities[i].string; i++) {
        kim_error err = KIM_NO_ERROR;
        krb5_context context = NULL;
        krb5_principal principal = NULL;
        krb5_principal identity_principal = NULL;
        kim_identity identity = NULL;

        printf (".");

        err = krb5_init_context (&context);
        fail_if_error (state, "krb5_init_context", err,
                       "while initializing context");

        if (!err) {
            err = krb5_parse_name (context, test_identities[i].string, &principal);
            fail_if_error (state, "krb5_parse_name", err,
                           "while creating krb5_principal for %s",
                           test_identities[i].string);
        }

        if (!err && !err) {
            err = kim_identity_create_from_string (&identity, test_identities[i].string);
            fail_if_error (state, "kim_identity_create_from_string", err,
                           "while creating the identity for %s",
                           test_identities[i].string);
        }

        if (!err && !err) {
            err = kim_identity_get_krb5_principal (identity, context, &identity_principal);
            fail_if_error (state, "kim_identity_get_krb5_principal", err,
                           "while getting the krb5_principal for %s",
                           test_identities[i].string);
        }

        if (!err && !err) {
            if (!krb5_principal_compare (context, principal, identity_principal)) {
                log_failure (state, "Principal and identity principal for %s do not match",
                             test_identities[i].string);
            }
        }

        kim_identity_free (&identity);
        if (identity_principal) { krb5_free_principal (context, identity_principal); }
        if (principal         ) { krb5_free_principal (context, principal); }
        if (context           ) { krb5_free_context (context); }
    }

    printf ("\n");

    end_test (state);
}

/* ------------------------------------------------------------------------ */
/*
void test_kim_identity_is_tgt_service (kim_test_state_t state)
{
    kim_count i = 0;

    start_test (state, "kim_identity_is_tgt_service");

    for (i = 0; test_identities[i].string; i++) {
        kim_error err = KIM_NO_ERROR;
        kim_identity_t identity = NULL;
        kim_boolean_t is_tgt_service = 0;

        printf (".");

        if (!err) {
            err = kim_identity_create_from_string (&identity, test_identities[i].string);
            fail_if_error (state, "kim_identity_create_from_string", err,
                           "while creating the identity for %s",
                           test_identities[i].string);
        }

        if (!err) {
            err = kim_identity_is_tgt_service (identity, &is_tgt_service);
            fail_if_error (state, "kim_identity_is_tgt_service", err,
                           "while determining if %s is a tgt service",
                           test_identities[i].string);
        }

        if (!err && (is_tgt_service != test_identities[i].is_tgt_service)) {
            log_failure (state, "Unexpected result from kim_identity_is_tgt_service for %s (got %d, expected %d)",
                         test_identities[i].string, is_tgt_service, test_identities[i].is_tgt_service);
        }

        kim_identity_free (&identity);
    }

     printf ("\n");

     end_test (state);
}
*/
