static inline void
utest_disjoint_set_union(void)
{
    bool pass;
    uint32 size;
    s_disjoint_set_t *disjoint_set;

    UNIT_TEST_BEGIN(disjoint_set_union);

    pass = true;
    size = 0x1234;

    disjoint_set = disjoint_set_create(size);

    disjoint_set_union(NULL, 0, 1);
    disjoint_set_union(disjoint_set, 0x1300, 0);
    disjoint_set_union(disjoint_set, 0, 0x1400);
    disjoint_set_union(disjoint_set, 0, 0);

    disjoint_set_union(disjoint_set, 0, 1);
    disjoint_set_union(disjoint_set, 0, 2);
    disjoint_set_union(disjoint_set, 0, 3);
    disjoint_set_union(disjoint_set, 4, 5);
    disjoint_set_union(disjoint_set, 4, 0x1000);
    disjoint_set_union(disjoint_set, 4, 0x1001);
    disjoint_set_union(disjoint_set, 0, 4);

    RESULT_CHECK_bool(true, disjoint_set_equivalent_p(disjoint_set, 0, 0), &pass);
    RESULT_CHECK_bool(true, disjoint_set_equivalent_p(disjoint_set, 0, 4), &pass);
    RESULT_CHECK_bool(true, disjoint_set_equivalent_p(disjoint_set, 0, 5), &pass);

    disjoint_set_destroy(&disjoint_set);
    UNIT_TEST_RESULT(disjoint_set_union, pass);
}
static void
utest_skip_linked_list_merge(void)
{
    bool pass;
    s_skip_linked_list_t *lm;
    s_skip_linked_list_t *ln;
    s_skip_linked_list_t *iter;
    s_skip_linked_list_t *tmp;

    pass = true;
    lm = NULL;
    UNIT_TEST_BEGIN(skip_linked_list_merge);

    ln = test_skip_linked_list_sample(0x103f);
    RESULT_CHECK_pointer(PTR_INVALID, skip_linked_list_merge(lm, lm), &pass);
    RESULT_CHECK_pointer(ln, skip_linked_list_merge(lm, ln), &pass);
    RESULT_CHECK_pointer(ln, skip_linked_list_merge(ln, ln), &pass);

    lm = skip_linked_list_create_with_key(0x8e290 - 0x245);
    ln = skip_linked_list_merge(ln, lm);
    iter = lm;

    while (iter) {
        tmp = skip_linked_list_find_key(ln, iter->key);
        RESULT_CHECK_sint32(tmp->key, iter->key, &pass);
        iter = skip_linked_list_next(iter);
    }
    skip_linked_list_destroy(&lm);

    skip_linked_list_destroy(&ln);
    UNIT_TEST_RESULT(skip_linked_list_merge, pass);
}
static inline void
utest_trie_tree_string_insert(void)
{
    bool pass;
    s_trie_tree_t *trie;

    UNIT_TEST_BEGIN(trie_tree_string_insert);

    pass = true;
    trie = trie_tree_create();

    trie_tree_string_insert(NULL, NULL);
    trie_tree_string_insert(trie, NULL);
    trie_tree_string_remove(trie, "");

    trie_tree_string_insert(trie, "");
    trie_tree_string_insert(trie, "asm");
    trie_tree_string_insert(trie, "auto");
    trie_tree_string_insert(trie, "break");
    trie_tree_string_insert(trie, "case");
    trie_tree_string_insert(trie, "char");
    trie_tree_string_insert(trie, "const");
    trie_tree_string_insert(trie, "continue");

    trie_tree_destroy(&trie);
    UNIT_TEST_RESULT(trie_tree_string_insert, pass);
}
static void
utest_skip_linked_list_find_key(void)
{
    bool pass;
    sint32 key;
    s_skip_linked_list_t *tmp;
    s_skip_linked_list_t *list;

    pass = true;
    list = NULL;
    key = 0xfffff;
    UNIT_TEST_BEGIN(skip_linked_list_find_key);

    RESULT_CHECK_pointer(PTR_INVALID, skip_linked_list_find_key(list, key), &pass);
    list = test_skip_linked_list_sample(0x103f);
    RESULT_CHECK_pointer(NULL, skip_linked_list_find_key(list, key), &pass);

    key = 0x1ffff;
    tmp = skip_linked_list_create_with_key(key);
    skip_linked_list_insert(&list, tmp);

    RESULT_CHECK_pointer(tmp, skip_linked_list_find_key(tmp, key), &pass);

    skip_linked_list_destroy(&list);
    UNIT_TEST_RESULT(skip_linked_list_find_key, pass);
}
static void
utest_skip_linked_list_contains_p(void)
{
    bool pass;
    sint32 key;
    s_skip_linked_list_t *tmp;
    s_skip_linked_list_t *list;

    pass = true;
    list = NULL;
    key = 0xfffff;
    UNIT_TEST_BEGIN(skip_linked_list_contains_p);

    RESULT_CHECK_bool(false, skip_linked_list_contains_p(list, NULL), &pass);
    list = test_skip_linked_list_sample(0x103f);
    RESULT_CHECK_bool(false, skip_linked_list_contains_p(list, NULL), &pass);

    tmp = skip_linked_list_create_with_key(0x2233);
    RESULT_CHECK_bool(false, skip_linked_list_contains_p(list, tmp), &pass);
    skip_linked_list_destroy(&tmp);

    key = 0xfff;
    while (key--) {
        tmp = skip_linked_list_find_key(list, key);
        if (tmp) {
            RESULT_CHECK_bool(true, skip_linked_list_contains_p(list, tmp), &pass);
        }
    }

    skip_linked_list_destroy(&list);
    UNIT_TEST_RESULT(skip_linked_list_contains_p, pass);
}
static inline void
utest_trie_tree_string_remove(void)
{
    bool pass;
    s_trie_tree_t *trie;

    UNIT_TEST_BEGIN(trie_tree_string_remove);

    pass = true;
    trie = trie_tree_create();

    trie_tree_string_remove(NULL, NULL);
    trie_tree_string_remove(trie, NULL);
    trie_tree_string_remove(trie, "");

    trie_tree_string_insert(trie, "asm");
    trie_tree_string_insert(trie, "auto");
    trie_tree_string_insert(trie, "break");
    trie_tree_string_insert(trie, "case");
    trie_tree_string_insert(trie, "char");
    trie_tree_string_insert(trie, "const");
    trie_tree_string_insert(trie, "continue");

    RESULT_CHECK_bool(true, trie_tree_string_matched_p(trie, "asm"), &pass);
    trie_tree_string_remove(trie, "asm");
    RESULT_CHECK_bool(false, trie_tree_string_matched_p(trie, "asm"), &pass);

    RESULT_CHECK_bool(true, trie_tree_string_matched_p(trie, "char"), &pass);
    trie_tree_string_remove(trie, "char");
    RESULT_CHECK_bool(false, trie_tree_string_matched_p(trie, "char"), &pass);

    trie_tree_destroy(&trie);
    UNIT_TEST_RESULT(trie_tree_string_remove, pass);
}
static inline void
utest_disjoint_set_find(void)
{
    bool pass;
    uint32 size;
    uint32 value;
    s_disjoint_set_t *disjoint_set;

    UNIT_TEST_BEGIN(disjoint_set_find);

    pass = true;
    size = 0x1234;

    disjoint_set = disjoint_set_create(size);

    disjoint_set_union(disjoint_set, 0, 1);
    disjoint_set_union(disjoint_set, 0, 2);
    disjoint_set_union(disjoint_set, 0, 3);
    disjoint_set_union(disjoint_set, 0, 4);
    disjoint_set_union(disjoint_set, 0, 0x1233);
    disjoint_set_union(disjoint_set, 0, 0x1200);

    value = disjoint_set_find(disjoint_set, 0);

    RESULT_CHECK_sint32(value, disjoint_set_find(disjoint_set, 1), &pass);
    RESULT_CHECK_sint32(value, disjoint_set_find(disjoint_set, 2), &pass);
    RESULT_CHECK_sint32(value, disjoint_set_find(disjoint_set, 0x1233), &pass);
    RESULT_CHECK_sint32(value, disjoint_set_find(disjoint_set, 0x1200), &pass);

    RESULT_CHECK_sint32(DISJOINT_ELE_INVALID, disjoint_set_find(disjoint_set, 0x1243), &pass);
    RESULT_CHECK_sint32(DISJOINT_ELE_INVALID, disjoint_set_find(NULL, 0x1243), &pass);

    disjoint_set_destroy(&disjoint_set);
    UNIT_TEST_RESULT(disjoint_set_find, pass);
}
bool math_eigen_test_rotate_with_arbitrary_quaternion()
{
	UNIT_TEST_BEGIN("rotate with arbitrary quaternion")
		Eigen::Quaternionf q = Eigen::Quaternionf(0.980671287f, 0.177366823f, 0.0705093816f, 0.0430502370f);
		Eigen::Vector3f v = Eigen::Vector3f(0.288588405f, -0.909195602f, 0.300133437f);

		success &= math_eigen_test_rotation_method_consistency(q, v);
	UNIT_TEST_COMPLETE()
}
//-- private functions -----
bool math_eigen_test_inverse_multiplication()
{
	UNIT_TEST_BEGIN("inverse multiplication")
		Eigen::Quaternionf q = Eigen::Quaternionf(0.980671287f, 0.177366823f, 0.0705093816f, 0.0430502370f);
		Eigen::Quaternionf q_inverse = eigen_quaternion_inverse(q);
		Eigen::Quaternionf q_identity = q * q_inverse;

		success &= q_identity.isApprox(Eigen::Quaternionf::Identity(), k_normal_epsilon);
		assert(success);
	UNIT_TEST_COMPLETE()
}
bool math_eigen_test_matrix_conversion()
{
	UNIT_TEST_BEGIN("matrix conversion")
		Eigen::Quaternionf q = Eigen::Quaternionf(0.980671287f, 0.177366823f, 0.0705093816f, 0.0430502370f);
		assert_eigen_quaternion_is_normalized(q);

		Eigen::Matrix3f m = eigen_quaternion_to_clockwise_matrix3f(q);
		Eigen::Quaternionf q_copy = eigen_matrix3f_to_clockwise_quaternion(m);

		success &= q.isApprox(q_copy, k_normal_epsilon);
		assert(success);
	UNIT_TEST_COMPLETE()
}
static void
utest_skip_linked_list_create_with_key(void)
{
    bool pass;
    sint32 key;
    s_skip_linked_list_t *list;

    pass = true;
    key = 0x431e2;
    UNIT_TEST_BEGIN(skip_linked_list_create_with_key);
    list = skip_linked_list_create_with_key(key);

    RESULT_CHECK_sint32(key, skip_linked_list_key(list), &pass);

    skip_linked_list_destroy(&list);
    UNIT_TEST_RESULT(skip_linked_list_create_with_key, pass);
}
static inline void
utest_trie_tree_create(void)
{
    bool pass;
    s_trie_tree_t *trie;

    UNIT_TEST_BEGIN(trie_tree_create);

    pass = true;
    trie = trie_tree_create();

    RESULT_CHECK_uint32(TRIE_TREE_ROOT, trie->val, &pass);
    RESULT_CHECK_NOT_EQUAL_pointer(NULL, trie->sub_queue, &pass);
    RESULT_CHECK_bool(false, trie->is_terminal, &pass);

    trie_tree_destroy(&trie);
    UNIT_TEST_RESULT(trie_tree_create, pass);
}
static inline void
utest_trie_tree_sequence_insert(void)
{
    bool pass;
    uint32 *sequence;
    uint32 len, limit;
    s_trie_tree_t *trie;

    UNIT_TEST_BEGIN(trie_tree_sequence_insert);

    pass = true;
    limit = 0xfff;
    trie = trie_tree_create();

    sequence = random_sequence_uint32_limited_obtain(1, 1);
    trie_tree_sequence_insert(NULL, NULL, 0);
    trie_tree_sequence_insert(trie, NULL, 0);
    trie_tree_sequence_insert(trie, sequence, 0);
    random_sequence_drop(sequence);

    len = 0x73b;
    sequence = random_sequence_uint32_limited_obtain(len, limit);
    trie_tree_sequence_insert(trie, sequence, len);
    random_sequence_drop(sequence);

    len = 0x124f;
    sequence = random_sequence_uint32_limited_obtain(len, limit);
    trie_tree_sequence_insert(trie, sequence, len);
    random_sequence_drop(sequence);

    len = 0x2be3;
    sequence = random_sequence_uint32_limited_obtain(len, limit);
    trie_tree_sequence_insert(trie, sequence, len);
    random_sequence_drop(sequence);

    len = 0x3a28;
    sequence = random_sequence_uint32_limited_obtain(len, limit);
    trie_tree_sequence_insert(trie, sequence, len);
    random_sequence_drop(sequence);

    trie_tree_destroy(&trie);
    UNIT_TEST_RESULT(trie_tree_sequence_insert, pass);
}
bool math_eigen_test_concatenation()
{
	UNIT_TEST_BEGIN("quaternion concatenation")
		Eigen::Quaternionf q_euler_pitch90 = eigen_euler_angles_to_quaternionf(Eigen::EulerAnglesf(0.f, 0.f, k_real_half_pi));
		Eigen::Quaternionf q_euler_yaw90 = eigen_euler_angles_to_quaternionf(Eigen::EulerAnglesf(0.f, k_real_half_pi, 0.f));
		Eigen::Vector3f v_x = Eigen::Vector3f::UnitX();

		// Make sure we get the answers we expect with angle axis rotation
		Eigen::Vector3f v_x_y90 = eigen_vector3f_clockwise_rotate(q_euler_yaw90, v_x);
		Eigen::Vector3f v_x_y90p90 = eigen_vector3f_clockwise_rotate(q_euler_pitch90, v_x_y90);

		// Make sure we get the answers we expect with euler angle rotation
		Eigen::Quaternionf q_euler_yaw90pitch90 = eigen_quaternion_concatenate(q_euler_yaw90, q_euler_pitch90);
		Eigen::Vector3f v_x_qy90p90 = eigen_vector3f_clockwise_rotate(q_euler_yaw90pitch90, v_x);

		success &= v_x_y90p90.isApprox(v_x_qy90p90, k_normal_epsilon);
		assert(success);
	UNIT_TEST_COMPLETE()
}
static inline void
utest_disjoint_set_destroy(void)
{
    bool pass;
    uint32 size;
    s_disjoint_set_t *disjoint_set;

    UNIT_TEST_BEGIN(disjoint_set_destroy);

    pass = true;
    size = 0x1234;

    disjoint_set = disjoint_set_create(size);
    RESULT_CHECK_NOT_EQUAL_pointer(NULL, disjoint_set, &pass);

    disjoint_set_destroy(&disjoint_set);
    RESULT_CHECK_pointer(NULL, disjoint_set, &pass);

    UNIT_TEST_RESULT(disjoint_set_destroy, pass);
}
static inline void
utest_trie_tree_destroy(void)
{
    bool pass;
    s_trie_tree_t *trie;

    UNIT_TEST_BEGIN(trie_tree_destroy);

    pass = true;

    trie = NULL;
    trie_tree_destroy(&trie);
    RESULT_CHECK_pointer(NULL, trie, &pass);

    trie = trie_tree_create();
    trie_tree_destroy(&trie);
    RESULT_CHECK_pointer(NULL, trie, &pass);

    UNIT_TEST_RESULT(trie_tree_destroy, pass);
}
static inline void
utest_trie_tree_sequence_matched_p(void)
{
    bool pass;
    uint32 *sequence;
    uint32 len, limit;
    s_trie_tree_t *trie;

    UNIT_TEST_BEGIN(trie_tree_sequence_matched_p);

    pass = true;
    limit = 0xfff;
    trie = trie_tree_create();

    sequence = random_sequence_uint32_limited_obtain(1, 1);
    RESULT_CHECK_bool(false, trie_tree_sequence_matched_p(NULL, NULL, 0), &pass);
    RESULT_CHECK_bool(false, trie_tree_sequence_matched_p(trie, NULL, 0), &pass);
    RESULT_CHECK_bool(false, trie_tree_sequence_matched_p(trie, sequence, 0), &pass);
    random_sequence_drop(sequence);

    len = 0x234;
    sequence = random_sequence_uint32_limited_obtain(len, limit);
    trie_tree_sequence_insert(trie, sequence, len);
    RESULT_CHECK_bool(true, trie_tree_sequence_matched_p(trie, sequence, len), &pass);
    random_sequence_drop(sequence);

    sequence = random_sequence_uint32_limited_obtain(len, limit);
    RESULT_CHECK_bool(false, trie_tree_sequence_matched_p(trie, sequence, len), &pass);
    random_sequence_drop(sequence);

    len = 0xf2de;
    sequence = random_sequence_uint32_limited_obtain(len, limit);
    trie_tree_sequence_insert(trie, sequence, len);
    RESULT_CHECK_bool(true, trie_tree_sequence_matched_p(trie, sequence, len), &pass);
    sequence[0]++;
    RESULT_CHECK_bool(false, trie_tree_sequence_matched_p(trie, sequence, len), &pass);
    random_sequence_drop(sequence);

    trie_tree_destroy(&trie);
    UNIT_TEST_RESULT(trie_tree_sequence_matched_p, pass);
}
bool math_eigen_test_rotate_with_angle_axis_quaternion()
{
	UNIT_TEST_BEGIN("rotate with angle axis quaternion")
		Eigen::Quaternionf q_pitch90 = eigen_quaternion_angle_axis(k_real_half_pi, Eigen::Vector3f::UnitX());
		Eigen::Quaternionf q_yaw90 = eigen_quaternion_angle_axis(k_real_half_pi, Eigen::Vector3f::UnitY());
		Eigen::Quaternionf q_roll90 = eigen_quaternion_angle_axis(k_real_half_pi, Eigen::Vector3f::UnitZ());
		Eigen::Quaternionf q_euler_roll90 = eigen_euler_angles_to_quaternionf(Eigen::EulerAnglesf(k_real_half_pi, 0.f, 0.f));
		Eigen::Quaternionf q_euler_yaw90 = eigen_euler_angles_to_quaternionf(Eigen::EulerAnglesf(0.f, k_real_half_pi, 0.f));
		Eigen::Quaternionf q_euler_pitch90 = eigen_euler_angles_to_quaternionf(Eigen::EulerAnglesf(0.f, 0.f, k_real_half_pi));
		Eigen::Vector3f v_x = Eigen::Vector3f::UnitX();
		Eigen::Vector3f v_y = Eigen::Vector3f::UnitY();
		Eigen::Vector3f v_z = Eigen::Vector3f::UnitZ();

		// Make sure we get the answers we expect with angle axis rotation
		Eigen::Vector3f v_x_rotated = eigen_vector3f_clockwise_rotate(q_yaw90, v_x);
		success &= v_x_rotated.isApprox(Eigen::Vector3f::UnitZ(), k_normal_epsilon);
		assert(success);
		Eigen::Vector3f v_y_rotated = eigen_vector3f_clockwise_rotate(q_roll90, v_y);
		success &= v_y_rotated.isApprox(Eigen::Vector3f::UnitX(), k_normal_epsilon);
		assert(success);
		Eigen::Vector3f v_z_rotated = eigen_vector3f_clockwise_rotate(q_pitch90, v_z);
		success &= v_z_rotated.isApprox(Eigen::Vector3f::UnitY(), k_normal_epsilon);
		assert(success);

		// Make sure we get the answers we expect with euler angle rotation
		v_x_rotated = eigen_vector3f_clockwise_rotate(q_euler_yaw90, v_x);
		success &= v_x_rotated.isApprox(Eigen::Vector3f::UnitZ(), k_normal_epsilon);
		assert(success);
		v_y_rotated = eigen_vector3f_clockwise_rotate(q_euler_roll90, v_y);
		success &= v_y_rotated.isApprox(Eigen::Vector3f::UnitX(), k_normal_epsilon);
		assert(success);
		v_z_rotated = eigen_vector3f_clockwise_rotate(q_euler_pitch90, v_z);
		success &= v_z_rotated.isApprox(Eigen::Vector3f::UnitY(), k_normal_epsilon);
		assert(success);

		// Make sure all rotation methods are consistent with each other
		success &= math_eigen_test_rotation_method_consistency(q_roll90, v_x);
		success &= math_eigen_test_rotation_method_consistency(q_pitch90, v_y);
		success &= math_eigen_test_rotation_method_consistency(q_yaw90, v_z);
	UNIT_TEST_COMPLETE()
}
bool math_eigen_test_euler_angles()
{
	UNIT_TEST_BEGIN("euler angles")
		Eigen::Quaternionf q_pitch90 = eigen_quaternion_angle_axis(k_real_half_pi, Eigen::Vector3f::UnitX());
		Eigen::Quaternionf q_yaw90 = eigen_quaternion_angle_axis(k_real_half_pi, Eigen::Vector3f::UnitY());
		Eigen::Quaternionf q_roll90 = eigen_quaternion_angle_axis(k_real_half_pi, Eigen::Vector3f::UnitZ());

		Eigen::Quaternionf q_euler_roll90 = eigen_euler_angles_to_quaternionf(Eigen::EulerAnglesf(k_real_half_pi, 0.f, 0.f));
		Eigen::Quaternionf q_euler_yaw90 = eigen_euler_angles_to_quaternionf(Eigen::EulerAnglesf(0.f, k_real_half_pi, 0.f));
		Eigen::Quaternionf q_euler_pitch90 = eigen_euler_angles_to_quaternionf(Eigen::EulerAnglesf(0.f, 0.f, k_real_half_pi));

		success &= q_pitch90.isApprox(q_euler_pitch90, k_normal_epsilon);
		assert(success);
		success &= q_yaw90.isApprox(q_euler_yaw90, k_normal_epsilon);
		assert(success);
		success &= q_roll90.isApprox(q_euler_roll90, k_normal_epsilon);
		assert(success);

		Eigen::EulerAnglesf euler_angles_pitch90= eigen_quaternionf_to_euler_angles(q_euler_pitch90);
		success &= is_nearly_equal(euler_angles_pitch90.get_heading_radians(), 0.f, k_normal_epsilon);
		success &= is_nearly_equal(euler_angles_pitch90.get_attitude_radians(), k_real_half_pi, k_normal_epsilon);
		success &= is_nearly_equal(euler_angles_pitch90.get_bank_radians(), 0.f, k_normal_epsilon);
		assert(success);

		Eigen::EulerAnglesf euler_angles_yaw90 = eigen_quaternionf_to_euler_angles(q_euler_yaw90);
		success &= is_nearly_equal(euler_angles_yaw90.get_heading_radians(), k_real_half_pi, k_normal_epsilon);
		success &= is_nearly_equal(euler_angles_yaw90.get_attitude_radians(), 0.f, k_normal_epsilon);
		success &= is_nearly_equal(euler_angles_yaw90.get_bank_radians(), 0.f, k_normal_epsilon);
		assert(success);

		Eigen::EulerAnglesf euler_angles_roll90 = eigen_quaternionf_to_euler_angles(q_euler_roll90);
		success &= is_nearly_equal(euler_angles_roll90.get_heading_radians(), 0.f, k_normal_epsilon);
		success &= is_nearly_equal(euler_angles_roll90.get_attitude_radians(), 0.f, k_normal_epsilon);
		success &= is_nearly_equal(euler_angles_roll90.get_bank_radians(), k_real_half_pi, k_normal_epsilon);
		assert(success);
	UNIT_TEST_COMPLETE()
}
static void
utest_skip_linked_list_remove(void)
{
    bool pass;
    uint32 count;
    s_skip_linked_list_t *tmp;
    s_skip_linked_list_t *list;

    tmp = NULL;
    pass = true;
    list = NULL;
    count = 0x24;
    UNIT_TEST_BEGIN(skip_linked_list_remove);

    RESULT_CHECK_pointer(PTR_INVALID, skip_linked_list_remove(&list, 0), &pass);
    list = test_skip_linked_list_sample(0x103f);

    tmp = list;
    RESULT_CHECK_pointer(tmp, skip_linked_list_remove(&list, tmp), &pass);
    skip_linked_list_destroy(&tmp);

    tmp = skip_linked_list_create();
    RESULT_CHECK_pointer(NULL, skip_linked_list_remove(&list, tmp), &pass);
    skip_linked_list_destroy(&tmp);

    while (count--) {
        tmp = skip_linked_list_find_key(list, count);
        if (NULL != tmp) {
            RESULT_CHECK_pointer(tmp, skip_linked_list_remove(&list, tmp), &pass);
            skip_linked_list_destroy(&tmp);
        }
    }

    skip_linked_list_destroy(&list);
    UNIT_TEST_RESULT(skip_linked_list_remove, pass);
}