11 #include <catch2/catch_test_macros.hpp>
12 #include <catch2/matchers/catch_matchers_string.hpp>
36 SCENARIO(
"NMODL can accept CR as return char for one line comment",
"[parser]") {
37 GIVEN(
"A comment defined with CR as return char") {
48 SCENARIO("NMODL can define macros using DEFINE keyword",
"[parser]") {
49 GIVEN(
"A valid macro definition") {
50 WHEN(
"DEFINE NSTEP 6") {
51 THEN(
"parser accepts without an error") {
55 WHEN(
"DEFINE NSTEP 6") {
56 THEN(
"parser accepts without an error") {
62 GIVEN(
"A macro with nested definition is not supported") {
63 WHEN(
"DEFINE SIX 6 DEFINE NSTEP SIX") {
64 THEN(
"parser throws an error") {
66 Catch::Matchers::ContainsSubstring(
"unexpected INVALID_TOKEN"));
71 GIVEN(
"A invalid macro definition with float value") {
72 WHEN(
"DEFINE NSTEP 6.0") {
73 THEN(
"parser throws an exception") {
75 Catch::Matchers::ContainsSubstring(
"unexpected REAL"));
80 GIVEN(
"A invalid macro definition with name and without value") {
81 WHEN(
"DEFINE NSTEP") {
82 THEN(
"parser throws an exception") {
84 Catch::Matchers::ContainsSubstring(
"expecting INTEGER"));
89 GIVEN(
"A invalid macro definition with name and value as a name") {
90 WHEN(
"DEFINE NSTEP SIX") {
91 THEN(
"parser throws an exception") {
93 Catch::Matchers::ContainsSubstring(
"expecting INTEGER"));
98 GIVEN(
"A invalid macro definition without name but with value") {
100 THEN(
"parser throws an exception") {
102 Catch::Matchers::ContainsSubstring(
"expecting NAME"));
108 SCENARIO(
"Macros can be used anywhere in the mod file") {
109 std::string nmodl_text = R
"(
115 WHEN("macro is used in parameter definition") {
116 THEN(
"parser accepts without an error") {
122 SCENARIO(
"NMODL parser accepts empty unit specification") {
123 std::string nmodl_text = R
"(
124 FUNCTION ssCB(kdf(), kds()) (mM) {
128 WHEN("FUNCTION is defined with empty unit") {
129 THEN(
"parser accepts without an error") {
135 SCENARIO(
"NMODL parser running number of valid NMODL constructs") {
137 auto test_case = construct.second;
138 GIVEN(test_case.name) {
139 THEN(
"Parser successfully parses : " + test_case.input) {
146 SCENARIO(
"NMODL parser running number of invalid NMODL constructs") {
148 auto test_case = construct.second;
149 GIVEN(test_case.name) {
150 THEN(
"Parser throws an exception while parsing : " + test_case.input) {
161 SCENARIO(
"Check that the parser doesn't crash when passing invalid INCLUDE constructs") {
162 GIVEN(
"An empty filename") {
164 Catch::Matchers::ContainsSubstring(
"empty filename"));
167 GIVEN(
"An missing included file") {
169 Catch::Matchers::ContainsSubstring(
170 "can not open file : \"unknown.file\""));
173 GIVEN(
"An invalid included file") {
175 Catch::Matchers::ContainsSubstring(
"unexpected End of file"));
179 SCENARIO(
"NEURON block can add CURIE information",
"[parser][represents]") {
180 GIVEN(
"A valid CURIE information statement") {
181 THEN(
"parser accepts without an error") {
187 GIVEN(
"Incomplete CURIE information statement") {
188 THEN(
"parser throws an error") {
190 Catch::Matchers::ContainsSubstring(
"Lexer Error"));
192 Catch::Matchers::ContainsSubstring(
"Lexer Error"));
198 SCENARIO(
"Check parents in valid NMODL constructs") {
203 GIVEN(construct.second.name) {
204 THEN(
"Check the parents in : " + construct.second.input) {
222 GIVEN(
"A differential equation") {
226 WHEN(prefix +
" EQUATION = " + test_case.equation +
" METHOD = " + test_case.method) {
227 THEN(prefix +
" SOLUTION = " + test_case.solution) {
228 auto expected_result = test_case.solution;
230 REQUIRE(result == expected_result);
247 const auto& ast_program =
driver.get_ast();
249 {nmodl::ast::AstNodeType::NEURON_BLOCK});
250 value = *(neuron_blocks.front()->get_token());
253 SCENARIO(
"Check if a NEURON block is parsed with correct location info in its token") {
254 GIVEN(
"A single NEURON block") {
257 std::stringstream ss;
258 std::string neuron_block = R
"(
261 USEION ca READ cai,cao WRITE ica
262 RANGE gcabar, m_inf, tau_m, alph1, alph2, KK, shift
267 REQUIRE(ss.str() == " NEURON at [1.1-5.1] type 296");