include(cmake_test/cmake_test)

ct_add_test(NAME "test__cpp_compare_names")
function("${test__cpp_compare_names}")
    include(cmakepp_lang/types/is_callable)

    set(sig0 a_fxn int bool)
    ct_add_section(NAME "names_match")
    function("${names_match}")
        set(sig1 a_fxn bool int)
        _cpp_compare_names(result sig0 sig1)
        ct_assert_equal(result TRUE)
    endfunction()

    ct_add_section(NAME "names_do_not_match")
    function("${names_do_not_match}")
        set(sig1 another_fxn bool int)
        _cpp_compare_names(result sig0 sig1)
        ct_assert_equal(result FALSE)
    endfunction()

    ct_add_section(NAME "case_insens_compare")
    function("${case_insens_compare}")
        set(sig1 a_FXN bool int)
        _cpp_compare_names(result sig0 sig1)
        ct_assert_equal(result TRUE)
    endfunction()
endfunction()

ct_add_test(NAME "test__cpp_compare_lengths")
function("${test__cpp_compare_lengths}")
    include(cmakepp_lang/types/is_callable)

    ct_add_section(NAME "no_args")
    function("${no_args}")
        set(sig0 a_fxn)

        ct_add_section(NAME "trial_sig_no_args")
        function("${trial_sig_no_args}")
            set(sig1 a_fxn)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()

        ct_add_section(NAME "trial_sig_more_args")
        function("${trial_sig_more_args}")
            set(sig1 a_fxn int)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()
    endfunction()

    ct_add_section(NAME "variadic_function")
    function("${variadic_function}")
        set(sig0 a_fxn args)

        ct_add_section(NAME "trial_sig_no_args")
        function("${trial_sig_no_args}")
            set(sig1 a_fxn)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()

        ct_add_section(NAME "trial_sig_more_args")
        function("${trial_sig_more_args}")
            set(sig1 a_fxn int)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()
    endfunction()

    ct_add_section(NAME "nonvariadic_one_arg")
    function("${nonvariadic_one_arg}")
        set(sig0 a_fxn int)

        ct_add_section(NAME "trial_sig_no_args")
        function("${trial_sig_no_args}")
            set(sig1 a_fxn)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()

        ct_add_section(NAME "trial_sig_one_arg")
        function("${trial_sig_one_arg}")
            set(sig1 a_fxn int)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()

        ct_add_section(NAME "trial_sig_more_args")
        function("${trial_sig_more_args}")
            set(sig1 a_fxn int bool)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()
    endfunction()

    ct_add_section(NAME "variadic_one_arg")
    function("${variadic_one_arg}")
        set(sig0 a_fxn int args)

        ct_add_section(NAME "trial_sig_no_args")
        function("${trial_sig_no_args}")
            set(sig1 a_fxn)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()

        ct_add_section(NAME "trial_sig_one_arg")
        function("${trial_sig_one_arg}")
            set(sig1 a_fxn int)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()

        ct_add_section(NAME "trial_sig_more_args")
        function("${trial_sig_more_args}")
            set(sig1 a_fxn int bool)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()
    endfunction()

    ct_add_section(NAME "nonvariadic_two_args")
    function("${nonvariadic_two_args}")
        set(sig0 a_fxn int bool)

        ct_add_section(NAME "trial_sig_no_args")
        function("${trial_sig_no_args}")
            set(sig1 a_fxn)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()

        ct_add_section(NAME "trial_sig_one_arg")
        function("${trial_sig_one_arg}")
            set(sig1 a_fxn int)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()

        ct_add_section(NAME "trial_sig_two_args")
        function("${trial_sig_two_args}")
            set(sig1 a_fxn int bool)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()

        ct_add_section(NAME "trial_sig_more_args")
        function("${trial_sig_more_args}")
            set(sig1 a_fxn int bool path)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()
    endfunction()

    ct_add_section(NAME "variadic_two_args")
    function("${variadic_two_args}")
        set(sig0 a_fxn int bool args)

        ct_add_section(NAME "trial_sig_no_args")
        function("${trial_sig_no_args}")
            set(sig1 a_fxn)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()

        ct_add_section(NAME "trial_sig_one_arg")
        function("${trial_sig_one_arg}")
            set(sig1 a_fxn int)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()

        ct_add_section(NAME "trial_sig_two_args")
        function("${trial_sig_two_args}")
            set(sig1 a_fxn int bool)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()

        ct_add_section(NAME "trial_sig_more_args")
        function("${trial_sig_more_args}")
            set(sig1 a_fxn int bool path)
            _cpp_compare_lengths(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()
    endfunction()
endfunction()

ct_add_test(NAME "test_cpp_is_callable")
function("${test_cpp_is_callable}")
    include(cmakepp_lang/types/is_callable)

    ct_add_section(NAME "test_signature")
    function("${test_signature}")
        set(CMAKEPP_LANG_DEBUG_MODE ON)

        ct_add_section(NAME "first_arg_desc" EXPECTFAIL)
        function("${first_arg_desc}")
            cpp_is_callable(TRUE a_list b_list)
        endfunction()

        ct_add_section(NAME "second_arg_desc" EXPECTFAIL)
        function("${second_arg_desc}")
            cpp_is_callable(result TRUE b_list)
        endfunction()

        ct_add_section(NAME "third_arg_desc" EXPECTFAIL)
        function("${third_arg_desc}")
            cpp_is_callable(result a_list FALSE)
        endfunction()

        ct_add_section(NAME "takes_three_args" EXPECTFAIL)
        function("${takes_three_args}")
            cpp_is_callable(result a_list b_list hello)
        endfunction()
    endfunction()

    ct_add_section(NAME "function_takes_no_args")
    function("${function_takes_no_args}")
        set(sig0 a_fxn)

        ct_add_section(NAME "trial_sig_no_args")
        function("${trial_sig_no_args}")
            set(sig1 a_fxn)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()

        ct_add_section(NAME "trial_sig_more_args")
        function("${trial_sig_more_args}")
            set(sig1 a_fxn int)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()
    endfunction()

    ct_add_section(NAME "variadic_function")
    function("${variadic_function}")
        set(sig0 a_fxn args)

        ct_add_section(NAME "trial_sig_no_args")
        function("${trial_sig_no_args}")
            set(sig1 a_fxn)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()

        ct_add_section(NAME "trial_sig_more_args")
        function("${trial_sig_more_args}")
            set(sig1 a_fxn int)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()
    endfunction()

    ct_add_section(NAME "nonvariadic_one_arg")
    function("${nonvariadic_one_arg}")
        set(sig0 a_fxn int)

        ct_add_section(NAME "trial_sig_takes_same_arg")
        function("${trial_sig_takes_same_arg}")
            set(sig1 a_fxn int)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()

        ct_add_section(NAME "trial_sig_takes_diff_args")
        function("${trial_sig_takes_diff_args}")
            set(sig1 a_fxn bool)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()
    endfunction()

    ct_add_section(NAME "variadic_one_arg")
    function("${variadic_one_arg}")
        set(sig0 a_fxn int args)

        ct_add_section(NAME "trial_sig_takes_same_args")
        function("${trial_sig_takes_same_args}")
            set(sig1 a_fxn int)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()

        ct_add_section(NAME "trial_sig_same_first_plus_others")
        function("${trial_sig_same_first_plus_others}")
            set(sig1 a_fxn int bool)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()

        ct_add_section(NAME "trial_sig_diff_args")
        function("${trial_sig_diff_args}")
            set(sig1 a_fxn bool)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()
    endfunction()

    ct_add_section(NAME "nonvariadic_two_args")
    function("${nonvariadic_two_args}")
        set(sig0 a_fxn int bool)

        ct_add_section(NAME "trial_sig_same_args")
        function("${trial_sig_same_args}")
            set(sig1 a_fxn int bool)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()

        ct_add_section(NAME "trial_sig_diff_first")
        function("${trial_sig_diff_first}")
            set(sig1 a_fxn bool bool)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()

        ct_add_section(NAME "trial_sig_diff_second")
        function("${trial_sig_diff_second}")
            set(sig1 a_fxn int int)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()
    endfunction()

    ct_add_section(NAME "variadic_two_args")
    function("${variadic_two_args}")
        set(sig0 a_fxn int bool args)

        ct_add_section(NAME "trial_sig_same_args")
        function("${trial_sig_same_args}")
            set(sig1 a_fxn int bool)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()

        ct_add_section(NAME "trial_sig_same_args_plus_others")
        function("${trial_sig_same_args_plus_others}")
            set(sig1 a_fxn int bool path)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result TRUE)
        endfunction()

        ct_add_section(NAME "trial_sig_diff_first")
        function("${trial_sig_diff_first}")
            set(sig1 a_fxn bool bool)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()

        ct_add_section(NAME "trial_sig_diff_second")
        function("${trial_sig_diff_second}")
            set(sig1 a_fxn int int)
            cpp_is_callable(result sig0 sig1)
            ct_assert_equal(result FALSE)
        endfunction()
    endfunction()
endfunction()
