Skip to content

Commit

Permalink
Remove brittle unit-test. (#1172)
Browse files Browse the repository at this point in the history
The removed test only checks if certain substrings are present. The
golden testing automatically adds these tests for any usecase.
Therefore, this test is not needed anymore.

The usecase for implementing non-specific current, will add a version
of a passive current; and test the values against the analytical
reference.

Ions are already covered by the `ionic` usecase.

Array variables are covered by the `cnexp_array` usecase.

Parameters coved by the `parameters` usecase.

Simple ODEs are covered by `cnexp_*` usecases.
  • Loading branch information
1uc committed Feb 26, 2024
1 parent 0a12b8e commit 2ea7f36
Showing 1 changed file with 0 additions and 256 deletions.
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

0 comments on commit 2ea7f36

Please sign in to comment.