Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove brittle unit-test. #1172

Merged
merged 1 commit into from
Feb 26, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
256 changes: 0 additions & 256 deletions test/unit/codegen/codegen_neuron_cpp_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,262 +48,6 @@ std::shared_ptr<CodegenNeuronCppVisitor> create_neuron_cpp_visitor(
return cv;
}


/// print entire code
std::string get_neuron_cpp_code(const std::string& nmodl_text) {
const auto& ast = NmodlDriver().parse_string(nmodl_text);
std::stringstream ss;
auto cvisitor = create_neuron_cpp_visitor(ast, nmodl_text, ss);
cvisitor->visit_program(*ast);
return ss.str();
}

std::string reindent_and_trim_text(const std::string& text) {
return reindent_text(stringutils::trim(text));
};

SCENARIO("Check NEURON codegen for simple MOD file", "[codegen][neuron_boilerplate]") {
GIVEN("A simple mod file with RANGE, ARRAY and ION variables") {
std::string const nmodl_text = R"(
TITLE unit test based on passive membrane channel

UNITS {
(mV) = (millivolt)
(mA) = (milliamp)
(S) = (siemens)
}

NEURON {
SUFFIX pas_test
USEION na READ ena WRITE ina
NONSPECIFIC_CURRENT i
RANGE g, e
RANGE ar
}

PARAMETER {
g = .001 (S/cm2) <0,1e9>
e = -70 (mV)
}

ASSIGNED {
v (mV)
i (mA/cm2)
ena (mV)
ina (mA/cm2)
ar[2]
}

INITIAL {
ar[0] = 1
}

BREAKPOINT {
SOLVE states METHOD cnexp
i = g*(v - e)
ina = g*(v - ena)
}

STATE {
s
}

DERIVATIVE states {
s' = ar[0]
}
)";
auto const generated = reindent_and_trim_text(get_neuron_cpp_code(nmodl_text));
THEN("Correct includes are printed") {
std::string expected_includes = R"(#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#include "mech_api.h"
#include "neuron/cache/mechanism_range.hpp"
#include "nrniv_mf.h"
#include "section_fwd.hpp")";

REQUIRE_THAT(generated, ContainsSubstring(reindent_and_trim_text(expected_includes)));
}
THEN("Correct number of variables are printed") {
std::string expected_num_variables =
R"(static constexpr auto number_of_datum_variables = 3;
static constexpr auto number_of_floating_point_variables = 10;)";

REQUIRE_THAT(generated,
ContainsSubstring(reindent_and_trim_text(expected_num_variables)));
}
THEN("Correct using-directives are printed ") {
std::string expected_using_directives = R"(namespace {
template <typename T>
using _nrn_mechanism_std_vector = std::vector<T>;
using _nrn_model_sorted_token = neuron::model_sorted_token;
using _nrn_mechanism_cache_range = neuron::cache::MechanismRange<number_of_floating_point_variables, number_of_datum_variables>;
using _nrn_mechanism_cache_instance = neuron::cache::MechanismInstance<number_of_floating_point_variables, number_of_datum_variables>;
using _nrn_non_owning_id_without_container = neuron::container::non_owning_identifier_without_container;
template <typename T>
using _nrn_mechanism_field = neuron::mechanism::field<T>;
template <typename... Args>
void _nrn_mechanism_register_data_fields(Args&&... args) {
neuron::mechanism::register_data_fields(std::forward<Args>(args)...);
}
} // namespace)";

REQUIRE_THAT(generated,
ContainsSubstring(reindent_and_trim_text(expected_using_directives)));
}
THEN("Correct namespace is printed") {
std::string expected_namespace = R"(namespace neuron {)";

REQUIRE_THAT(generated, ContainsSubstring(reindent_and_trim_text(expected_namespace)));
}
THEN("Correct channel information are printed") {
std::string expected_channel_info = R"(/** channel information */
static const char *mechanism_info[] = {
"7.7.0",
"pas_test",
"g_pas_test",
"e_pas_test",
0,
"i_pas_test",
"ar_pas_test[2]",
0,
"s_pas_test",
0,
0
};)";

REQUIRE_THAT(generated,
ContainsSubstring(reindent_and_trim_text(expected_channel_info)));
}
THEN("Correct global variables are printed") {
std::string expected_global_variables =
R"(static neuron::container::field_index _slist1[1], _dlist1[1];)";

REQUIRE_THAT(generated,
ContainsSubstring(reindent_and_trim_text(expected_global_variables)));
}
THEN("Correct pas_test_Instance") {
std::string expected =
R"( struct pas_test_Instance {
double* g{};
double* e{};
double* i{};
double* ar{};
double* s{};
double* ena{};
double* ina{};
double* Ds{};
double* v_unused{};
double* g_unused{};
const double* const* ion_ena{};
double* const* ion_ina{};
double* const* ion_dinadv{};
pas_test_Store* global{&pas_test_global};
};)";

REQUIRE_THAT(generated, ContainsSubstring(reindent_and_trim_text(expected)));
}
THEN("Correct HOC global variables are printed") {
std::string expected_hoc_global_variables =
R"(/** connect global (scalar) variables to hoc -- */
static DoubScal hoc_scalar_double[] = {
{nullptr, nullptr}
};


/** connect global (array) variables to hoc -- */
static DoubVec hoc_vector_double[] = {
{nullptr, nullptr, 0}
};)";

REQUIRE_THAT(generated,
ContainsSubstring(reindent_and_trim_text(expected_hoc_global_variables)));
}
THEN("Placeholder nrn_cur function is printed") {
std::string expected_placeholder_nrn_cur =
R"(void nrn_cur_pas_test(_nrn_model_sorted_token const& _sorted_token, NrnThread* _nt, Memb_list* _ml_arg, int _type) {})";

REQUIRE_THAT(generated,
ContainsSubstring(reindent_and_trim_text(expected_placeholder_nrn_cur)));
}
THEN("Placeholder nrn_state function is printed") {
std::string expected_placeholder_nrn_state =
R"(void nrn_state_pas_test(_nrn_model_sorted_token const& _sorted_token, NrnThread* _nt, Memb_list* _ml_arg, int _type) {)";

REQUIRE_THAT(generated,
ContainsSubstring(reindent_and_trim_text(expected_placeholder_nrn_state)));
}
THEN("Initialization function for slist/dlist is printed correctly") {
std::string expected_initlists_s_var = "_slist1[0] = {4, 0};";
std::string expected_initlists_Ds_var = "_dlist1[0] = {7, 0};";

REQUIRE_THAT(generated,
ContainsSubstring(reindent_and_trim_text(expected_initlists_s_var)));
REQUIRE_THAT(generated,
ContainsSubstring(reindent_and_trim_text(expected_initlists_Ds_var)));
}
THEN("Placeholder registration function is printed") {
std::string expected_placeholder_reg = R"CODE(/** register channel with the simulator */
extern "C" void __test_reg() {
_initlists();

ion_reg("na", -10000.);

_na_sym = hoc_lookup("na_ion");

register_mech(mechanism_info, nrn_alloc_pas_test, nrn_cur_pas_test, nrn_jacob_pas_test, nrn_state_pas_test, nrn_init_pas_test, hoc_nrnpointerindex, 1);

mech_type = nrn_get_mechtype(mechanism_info[1]);
_nrn_mechanism_register_data_fields(mech_type,
_nrn_mechanism_field<double>{"g"} /* 0 */,
_nrn_mechanism_field<double>{"e"} /* 1 */,
_nrn_mechanism_field<double>{"i"} /* 2 */,
_nrn_mechanism_field<double>{"ar", 2} /* 3 */,
_nrn_mechanism_field<double>{"s"} /* 4 */,
_nrn_mechanism_field<double>{"ena"} /* 5 */,
_nrn_mechanism_field<double>{"ina"} /* 6 */,
_nrn_mechanism_field<double>{"Ds"} /* 7 */,
_nrn_mechanism_field<double>{"v_unused"} /* 8 */,
_nrn_mechanism_field<double>{"g_unused"} /* 9 */,
_nrn_mechanism_field<double*>{"ion_ena", "na_ion"} /* 0 */,
_nrn_mechanism_field<double*>{"ion_ina", "na_ion"} /* 1 */,
_nrn_mechanism_field<double*>{"ion_dinadv", "na_ion"} /* 2 */
);

hoc_register_prop_size(mech_type, 10, 3);
hoc_register_dparam_semantics(mech_type, 0, "na_ion");
hoc_register_dparam_semantics(mech_type, 1, "na_ion");
hoc_register_dparam_semantics(mech_type, 2, "na_ion");
hoc_register_var(hoc_scalar_double, hoc_vector_double, hoc_intfunc);
hoc_register_npy_direct(mech_type, npy_direct_func_proc);
})CODE";

REQUIRE_THAT(generated,
ContainsSubstring(reindent_and_trim_text(expected_placeholder_reg)));
}
}
GIVEN("A simple point process mod file") {
std::string const nmodl_text = R"(
NEURON {
POINT_PROCESS test_pp
}
)";
THEN("Correct mechanism registration function is called") {
std::string expected_placeholder_point_reg =
"_pointtype = point_register_mech(mechanism_info, nrn_alloc_test_pp, nullptr, "
"nullptr, nullptr, nrn_init_test_pp, hoc_nrnpointerindex, 1, _hoc_create_pnt, "
"_hoc_destroy_pnt, _member_func);";

auto const generated = reindent_and_trim_text(get_neuron_cpp_code(nmodl_text));

REQUIRE_THAT(generated,
ContainsSubstring(reindent_and_trim_text(expected_placeholder_point_reg)));
}
}
}


SCENARIO("Check whether PROCEDURE and FUNCTION need setdata call", "[codegen][needsetdata]") {
GIVEN("mod file with GLOBAL and RANGE variables used in FUNC and PROC") {
std::string input_nmodl = R"(
Expand Down
Loading