LCOV - code coverage report
Current view: top level - lps/test - linearization_test2.cpp (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 135 135 100.0 %
Date: 2024-04-19 03:43:27 Functions: 54 54 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Wieger Wesselink, Jan Friso Groote
       2             : // Copyright: see the accompanying file COPYING or copy at
       3             : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING
       4             : //
       5             : // Distributed under the Boost Software License, Version 1.0.
       6             : // (See accompanying file LICENSE_1_0.txt or copy at
       7             : // http://www.boost.org/LICENSE_1_0.txt)
       8             : //
       9             : /// \file linearization_test.cpp
      10             : /// \brief Add your file description here.
      11             : 
      12             : #define BOOST_TEST_MODULE linearization_test
      13             : #include <boost/test/included/unit_test.hpp>
      14             : 
      15             : #ifndef MCRL2_SKIP_LONG_TESTS
      16             : 
      17             : #include "mcrl2/data/detail/rewrite_strategies.h"
      18             : #include "mcrl2/lps/is_well_typed.h"
      19             : #include "mcrl2/lps/linearise.h"
      20             : 
      21             : using namespace mcrl2;
      22             : using namespace mcrl2::lps;
      23             : 
      24             : typedef data::rewriter::strategy rewrite_strategy;
      25             : typedef std::vector<rewrite_strategy> rewrite_strategy_vector;
      26             : 
      27         156 : void run_linearisation_instance(const std::string& spec, const t_lin_options& options, bool expect_success)
      28             : {
      29         156 :   if (expect_success)
      30             :   {
      31         144 :     BOOST_CHECK(mcrl2::lps::detail::is_well_typed(linearise(spec, options)));
      32             :   }
      33             :   else
      34             :   {
      35          24 :     BOOST_CHECK_THROW(linearise(spec, options), mcrl2::runtime_error);
      36             :   }
      37         156 : }
      38             : 
      39          26 : void run_linearisation_test_case(const std::string& spec, const bool expect_success = true)
      40             : {
      41             :   // Set various rewrite strategies
      42          26 :   rewrite_strategy_vector rewrite_strategies = data::detail::get_test_rewrite_strategies(false);
      43          26 :   std::clog << "Tested specification:\n" << spec << "\n------------------------------------\n";
      44             : 
      45          52 :   for (rewrite_strategy_vector::const_iterator i = rewrite_strategies.begin(); i != rewrite_strategies.end(); ++i)
      46             :   {
      47          26 :     std::clog << std::endl << "Testing with rewrite strategy " << *i << std::endl;
      48             : 
      49          26 :     t_lin_options options;
      50          26 :     options.rewrite_strategy=*i;
      51             : 
      52          26 :     std::clog << "  Default options" << std::endl;
      53          26 :     run_linearisation_instance(spec, options, expect_success);
      54             : 
      55          26 :     std::clog << "  Linearisation method regular2" << std::endl;
      56          26 :     options.lin_method=lmRegular2;
      57          26 :     run_linearisation_instance(spec, options, expect_success);
      58             : 
      59          26 :     std::clog << "  Linearisation method stack" << std::endl;
      60          26 :     options.lin_method=lmStack;
      61          26 :     run_linearisation_instance(spec, options, expect_success);
      62             : 
      63          26 :     std::clog << "  Linearisation method stack; binary enabled" << std::endl;
      64          26 :     options.binary=true;
      65          26 :     run_linearisation_instance(spec, options, expect_success);
      66             : 
      67          26 :     std::clog << "  Linearisation method regular; binary enabled" << std::endl;
      68          26 :     options.lin_method=lmRegular;
      69          26 :     run_linearisation_instance(spec, options, expect_success);
      70             : 
      71          26 :     std::clog << "  Linearisation method regular; no intermediate clustering" << std::endl;
      72          26 :     options.binary=false; // reset binary
      73          26 :     options.no_intermediate_cluster=true;
      74          26 :     run_linearisation_instance(spec, options, expect_success);
      75             :   }
      76          26 : }
      77             : 
      78           2 : BOOST_AUTO_TEST_CASE(various_case_27)
      79             : {
      80             :   const std::string various_case_27=
      81             :     "act a:Pos;\n"
      82             :     "proc P(id,n:Pos)=(id<n) -> a(n).P(id,n);\n"
      83             :     "     Q(n:Pos)=P(1,n)||P(2,n)||P(3,n);\n"
      84           1 :     "init Q(15);\n";
      85           1 :   run_linearisation_test_case(various_case_27);
      86           1 : }
      87             : 
      88           2 : BOOST_AUTO_TEST_CASE(various_case_28)
      89             : {
      90             :   const std::string various_case_28=
      91             :     "sort A=List(Nat->Nat);"
      92             :     "T=struct f(Nat->Nat);"
      93             :     "act b:A;"
      94             :     "proc P(a:A)=b(a).P([]);"
      95           1 :     "init P([lambda n:Nat.n]);";
      96           1 :   run_linearisation_test_case(various_case_28);
      97           1 : }
      98             : 
      99           2 : BOOST_AUTO_TEST_CASE(various_case_29)
     100             : {
     101             :   const std::string various_case_29=
     102             :     "sort Data = struct x;"
     103             :     "Coloured = struct flow(data : Data) | noflowG | noflowR;"
     104             :     "act A, B : Coloured;"
     105             :     "proc Sync = ( (A(noflowG) | B(noflowR))  + "
     106             :     "     (A(noflowR) | B(noflowR)) + "
     107             :     "     (sum d : Data.(A(flow(d)) | B(flow(d)))) "
     108             :     "  ).Sync;"
     109           1 :     "init Sync;";
     110           1 :   run_linearisation_test_case(various_case_29);
     111           1 : }
     112             : 
     113             : // The test case below is to test whether the elements of a multi-action
     114             : // are dealt with properly when they occur in a subexpression. The linearised
     115             : // process below should have three and not two summand.
     116           2 : BOOST_AUTO_TEST_CASE(various_case_30)
     117             : {
     118             :   const std::string various_case_30=
     119             :     "act a;"
     120             :     "    b,b':Nat;"
     121           1 :     "init a.(b(0)|b'(0))+a.(b(0)|b(0));";
     122           1 :   run_linearisation_test_case(various_case_30);
     123           1 : }
     124             : 
     125           2 : BOOST_AUTO_TEST_CASE(various_case_31)
     126             : {
     127             :   const std::string various_case_31=
     128             :     "act a:List(List(Nat));"
     129             :     "proc X(x:List(List(Nat)))=a(x).delta;"
     130           1 :     "init X([[]]);";
     131           1 :   run_linearisation_test_case(various_case_31);
     132           1 : }
     133             : 
     134             : // Original name: LR2plus.mcrl2
     135             : // This example can only be parsed unambiguously by an LR(k) parser generator
     136             : // for the current grammar, where k > 1. Namely, process expression 'a + tau'
     137             : // cannot be parsed unambiguously. After parsing the identifier 'a', it has to
     138             : // be determined if 'a' is an action or process reference, or if 'a' is a data
     139             : // expression, viz. part of the left hand side of a conditional process
     140             : // expression. With a lookahead of 1, we may only use the '+' as extra
     141             : // information, which is not enough, because this symbol is also ambiguous.
     142             : 
     143           2 : BOOST_AUTO_TEST_CASE(various_case_LR2plus)
     144             : {
     145             :   const std::string various_case_LR2plus=
     146             :     "act\n"
     147             :     " a;\n\n"
     148             :     "init\n"
     149           1 :     " a + tau;";
     150           1 :   run_linearisation_test_case(various_case_LR2plus);
     151           1 : }
     152             : 
     153             : // Original name: LR2par.mcrl2
     154             : // This example can only be parsed unambiguously by an LR(k) parser generator
     155             : // for the current grammar, where k > 1. Namely, process expression '(a)'
     156             : // cannot be parsed unambiguously. After parsing the left parenthesis '(', it
     157             : // has to be determined if it is part of a process or data expression, viz.
     158             : // part of the left hand side of a conditional process expression. With a
     159             : // lookahead of 1, we may only use the identifier 'a' as extra information,
     160             : // which is not enough, because this symbol is also ambiguous.
     161             : 
     162           2 : BOOST_AUTO_TEST_CASE(various_case_LR2par)
     163             : {
     164             :   const std::string various_case_LR2par=
     165             :     "act\n"
     166             :     " a;\n\n"
     167             :     "init\n"
     168           1 :     " (a);";
     169           1 :   run_linearisation_test_case(various_case_LR2par);
     170           1 : }
     171             : 
     172             : 
     173             : // This test case is a simple test to test sort normalisation in the lineariser,
     174             : // added because assertion failures in the domineering example were observed 
     175           2 : BOOST_AUTO_TEST_CASE(various_case_32)
     176             : {
     177             :   const std::string various_case_32 =
     178             :     "sort Position = struct Full | Empty;\n"
     179             :     "     Row = List(Position);\n"
     180             :     "\n"
     181             :     "proc P(r:Row) = delta;\n"
     182           1 :     "init P([Empty]);\n"
     183             :     ;
     184           1 :   run_linearisation_test_case(various_case_32);
     185           1 : }
     186             : 
     187             : // This test case is a test to check whether constant elimination in the
     188             : // linearizer goes well. This testcase is inspired by an example by Chilo
     189             : // van Best. The problem is that the constant x:Nat below may not be
     190             : // recorded in the assignment list of process P, and therefore forgotten 
     191           2 : BOOST_AUTO_TEST_CASE(various_case_33)
     192             : {
     193             :   const std::string various_case_33 =
     194             :     "act  a:Nat; "
     195             :     "proc P(x:Nat,b:Bool,r:Real) = a(x).P(x,!b,r); "
     196             :     "     P(x:Nat) = P(x,true,1); "
     197           1 :     "init P(1); "
     198             :     ;
     199           1 :   run_linearisation_test_case(various_case_33);
     200           1 : }
     201             : 
     202             : // The test case below checks whether the alphabet conversion does not accidentally
     203             : // reverse the order of hide and sum operators. If this happens the linearizer will
     204             : // not be able to linearize this process 
     205           2 : BOOST_AUTO_TEST_CASE(various_case_34)
     206             : {
     207             :   const std::string various_case_34 =
     208             :     "act a; "
     209             : 
     210             :     "proc X = a.X;"
     211             :     "proc Y = sum n:Nat. X;"
     212             : 
     213           1 :     "init hide({a}, sum n:Nat. X);"
     214             :     ;
     215           1 :   run_linearisation_test_case(various_case_34);
     216           1 : }
     217             : 
     218           2 : BOOST_AUTO_TEST_CASE(various_case_par)
     219             : {
     220             :   const std::string various_par =
     221             :     "act a;\n"
     222           1 :     "init a || a;\n"
     223             :     ;
     224           1 :   run_linearisation_test_case(various_par);
     225           1 : }
     226             : 
     227           2 : BOOST_AUTO_TEST_CASE(gpa_10_3)
     228             : {
     229             :   const std::string various_gpa_10_3 =
     230             :     "act\n"
     231             :     "  c,r_dup, s_dup1, s_dup2, r_inc, s_inc, r_mul1, r_mul2, s_mul: Int;\n"
     232             :     "proc\n"
     233             :     "  Dup = sum x:Int. r_dup(x) | s_dup1(x) | s_dup2(x) . Dup;\n"
     234             :     "  Inc = sum x:Int. r_inc(x) | s_inc(x+1) . Inc;\n"
     235             :     "  Mul = sum x,y:Int. r_mul1(x) | r_mul2(y) | s_mul(x*y) . Mul;\n"
     236             :     "  Dim = allow({r_dup | s_mul},\n"
     237             :     "          hide({c},comm({s_dup1 | r_mul1 -> c , s_dup2 | r_inc -> c, s_inc | r_mul2 ->c},\n"
     238             :     "            Dup || Inc || Mul\n"
     239             :     "          ))\n"
     240             :     "        );\n"
     241           1 :     "init Dim;\n"
     242             :     ;
     243           1 :   run_linearisation_test_case(various_gpa_10_3);
     244           1 : }
     245             : 
     246             : /* The following test cases fail because the n-parallel support in the alphabet reductions is broken
     247             :  * (Checked JK 31/8/2010)
     248             :  */
     249             : /*
     250             : BOOST_AUTO_TEST_CASE(philosophers)
     251             : {
     252             :   const std::string various_philosophers =
     253             :     "map K: Pos;\n"
     254             :     "eqn K = 10;\n"
     255             :     "act get,_get,__get,put,_put,__put: Pos#Pos;\n"
     256             :     "    eat: Pos;\n"
     257             :     "proc\n"
     258             :     "  Phil(n:Pos) = _get(n,n)._get(n,if(n==K,1,n+1)).eat(n)._put(n,n)._put(n,if(n==K,1,n+1)).Phil(n);\n"
     259             :     "  Fork(n:Pos) = sum m:Pos.get(m,n).put(m,n).Fork(n);\n"
     260             :     "  ForkPhil(n:Pos) = Fork(n) || Phil(n);\n"
     261             :     "  KForkPhil(p:Pos) =\n"
     262             :     "    (p>1) -> (ForkPhil(p)||KForkPhil(max(p-1,1)))<>ForkPhil(1);\n"
     263             :     "init allow( { __get, __put, eat },\n"
     264             :     "       comm( { get|_get->__get, put|_put->__put },\n"
     265             :     "         KForkPhil(K)\n"
     266             :     "     ));\n"
     267             :     ;
     268             :   run_linearisation_test_case(various_philosophers);
     269             : }
     270             : 
     271             : BOOST_AUTO_TEST_CASE(philosophers_nat)
     272             : {
     273             :   const std::string various_philosophers_nat =
     274             :     "map K: Nat;\n"
     275             :     "eqn K = 10;\n"
     276             :     "act get,_get,__get,put,_put,__put: Nat#Nat;\n"
     277             :     "    eat: Nat;\n"
     278             :     "proc\n"
     279             :     "  Phil(n:Nat) = _get(n,n)._get(n,if(n==K,1,n+1)).eat(n)._put(n,n)._put(n,if(n==K,1,n+1)).Phil(n);\n"
     280             :     "  Fork(n:Nat) = sum m:Nat.get(m,n).put(m,n).Fork(n);\n"
     281             :     "  ForkPhil(n:Nat) = Fork(n) || Phil(n);\n"
     282             :     "  KForkPhil(p:Nat) =\n"
     283             :     "    (p>1) -> (ForkPhil(p)||KForkPhil(max(p-1,1)))<>ForkPhil(1);\n"
     284             :     "init allow( { __get, __put, eat },\n"
     285             :     "       comm( { get|_get->__get, put|_put->__put },\n"
     286             :     "         KForkPhil(K)\n"
     287             :     "     ));\n"
     288             :     ;
     289             :   run_linearisation_test_case(various_philosophers_nat);
     290             : }
     291             : */
     292             : 
     293           2 : BOOST_AUTO_TEST_CASE(sort_aliases)
     294             : {
     295             :   const std::string various_sort_aliases =
     296             :     "sort Bits = struct b0|b1;\n"
     297             :     "     t_sys_regset_fsm_state = Bits;\n"
     298             :     "     t_timer_counter_fsm_state = Bits;\n"
     299             :     "map  timer_counter_fsm_state_idle: t_timer_counter_fsm_state;\n"
     300             :     "act  a:Bits;\n"
     301             :     "proc P(d:Bits)=a(d).delta;\n"
     302             :     "glob globd:Bits;\n"
     303           1 :     "init P(globd);\n"
     304             :     ;
     305           1 :   run_linearisation_test_case(various_sort_aliases);
     306           1 : }
     307             : 
     308           2 : BOOST_AUTO_TEST_CASE(test_aliases_complex)
     309             : {
     310             :   const std::string spec =
     311             :     "sort\n"
     312             :     "  Bits = struct singleBit (bit: Bool)?isSingleBit | bitVector (bitVec:List(Bool))?isBitVector;\n"
     313             :     "  t_sys_regset_fsm_state = Bits;\n"
     314             :     "  t_timer_counter_fsm_state = Bits;\n"
     315             :     "map\n"
     316             :     "  repeat : Bool # Nat -> Bits;\n"
     317             :     "  repeat_rec : Bool # Nat -> List(Bool);\n"
     318             :     "var\n"
     319             :     "  b:Bool;\n"
     320             :     "  n:Nat;\n"
     321             :     "eqn\n"
     322             :     "  repeat(b,n) = if(n <= 1, singleBit(b), bitVector(repeat_rec(b,n)));\n"
     323             :     "act a:Bits;\n"
     324           1 :     "init a(repeat(true,32)).delta;\n";
     325           1 :   run_linearisation_test_case(spec);
     326           1 : }
     327             : 
     328           2 : BOOST_AUTO_TEST_CASE(test_bug_775a)
     329             : {
     330             :   const std::string spec =
     331             :     "sort V = struct v1( l: Bool  );\n"
     332             :     "act  a:  List( Bool );\n"
     333             :     "sort B = Bool -> List(Bool);\n"
     334             :     "proc X( M: B ) = \n"
     335             :     "  sum v:V.  a( [] ) \n"
     336             :     "+ sum v:V.  a( M(l(v)))\n"
     337             :     ";\n"
     338           1 :     "init X( lambda i: Bool. [] );\n";
     339           1 :   run_linearisation_test_case(spec);
     340           1 : }
     341             : 
     342           2 : BOOST_AUTO_TEST_CASE(test_bug_775b)
     343             : {
     344             :   const std::string spec =
     345             :     "sort V = struct v1( l: Bool  );\n"
     346             :     "act  a:  List( Bool );\n"
     347             :     "sort B = Bool -> List(Bool);\n"
     348             :     "proc X( M: B ) = \n"
     349             :     "  sum v:V.  a( M(l(v)))\n"
     350             :     "+ sum v:V.  a( [] ) \n"
     351             :     ";\n"
     352           1 :     "init X( lambda i: Bool. [] );\n";
     353           1 :   run_linearisation_test_case(spec);
     354           1 : }
     355             : 
     356           2 : BOOST_AUTO_TEST_CASE(test_bug_alphabet_reduction)
     357             : {
     358             :   const std::string spec =
     359             :     "sort Variables = struct s;\n"
     360             :     "\n"
     361             :     "act send_c, recv_c, comm_c: Bool;\n"
     362             :     "    chng: Set(Variables);\n"
     363             :     "\n"
     364             :     "init allow( { comm_c | chng | chng } ,\n"
     365             :     "  comm( { send_c | recv_c -> comm_c,\n"
     366             :     "          chng | chng -> chng},\n"
     367             :     "          send_c(false) | chng( {} ) || recv_c(false) | chng( {s} )\n"
     368           1 :     "       ) );\n";
     369           1 :   run_linearisation_test_case(spec);
     370           1 : }
     371             : 
     372           2 : BOOST_AUTO_TEST_CASE(test_bug_alphabet_reduction1)
     373             : {
     374             :   const std::string spec =
     375             :     "act a: Bool;\n"
     376             :     "    b: Nat;\n"
     377             :     "\n"
     378             :     "proc X = allow( {b | a | a },\n"
     379             :     "          a(true)| b(5) | a(false) );\n"
     380             :     "\n"
     381           1 :     "init X;\n";
     382           1 :   run_linearisation_test_case(spec);
     383           1 : }
     384             : 
     385             : // The testcase below is added because the typechecker could not deal with this
     386             : // case. The three options for the action a caused it to become confused.
     387           2 : BOOST_AUTO_TEST_CASE(test_multiple_action_types)
     388             : {
     389             :   const std::string spec =
     390             :      "sort Id = Pos;\n"
     391             :      "\n"
     392             :      "map FALSE: Id -> Bool;\n"
     393             :      "var n: Id;\n"
     394             :      "eqn FALSE(n) = false;\n"
     395             :      "\n"
     396             :      "act a: (Id -> Bool);\n"
     397             :      "    a: Bool;\n"
     398             :      "    a: Pos;\n"
     399             :      "\n"
     400             :      "proc P = a(FALSE) . delta;\n"
     401           1 :      "init P;\n";
     402             : 
     403           1 :   run_linearisation_test_case(spec);
     404           1 : }
     405             : 
     406             : // Test case for bug #1085
     407           2 : BOOST_AUTO_TEST_CASE(bug_1085)
     408             : {
     409             :   const std::string spec =
     410             :     "proc P = tau. a | b | c;\n"
     411             :     "act a,b,c;\n"
     412           1 :     "init P;\n";
     413             : 
     414           1 :   run_linearisation_test_case(spec);
     415           1 : }
     416             : 
     417           2 : BOOST_AUTO_TEST_CASE(bug_978)
     418             : {
     419             :   const std::string spec =
     420             :      "act rd,wr:Bool;\n"
     421             :      "proc R(a,b : Bool) = \n"
     422             :      "        rd(a) . R() +\n"
     423             :      "        rd(b) . R() + \n"
     424             :      "        sum b:Bool. wr(b) . R(a=b);\n"
     425           1 :      "init R(true,true);\n";
     426           1 :   run_linearisation_test_case(spec);
     427           1 : }
     428             : 
     429           2 : BOOST_AUTO_TEST_CASE(not_properly_ordered_assignments)
     430             : {
     431             :   const std::string spec =
     432             :      "proc R(a,b : Bool) = \n"
     433             :      "        tau . R(a=true,b=false) +\n"
     434             :      "        tau . R(b=false,a=false); \n"
     435           1 :      "init R(true,true);\n";
     436           1 :   run_linearisation_test_case(spec);
     437           1 : }
     438             : 
     439           2 : BOOST_AUTO_TEST_CASE(the_bound_c_may_not_show_up_in_linear_process)
     440             : {
     441             :   const std::string spec =
     442             :      "act \n"
     443             :      "rcv_req; \n"
     444             :      "snd_return : Bool; \n"
     445             :      "internal; \n"
     446             :      " \n"
     447             :      "proc \n"
     448             :      " \n"
     449             :      "test1 = \n"
     450             :      "( \n"
     451             :      "    rcv_req. \n"
     452             :      "    sum c:Bool. \n"
     453             :      "    ( \n"
     454             :      "        internal.snd_return(c) \n"
     455             :      "    ). \n"
     456             :      "    test1 \n"
     457             :      "); \n"
     458             :      " \n"
     459           1 :      "init test1; \n";
     460           1 :   run_linearisation_test_case(spec);
     461           1 : }
     462             : 
     463           2 : BOOST_AUTO_TEST_CASE(process_parameters_with_different_types_can_cause_problems)
     464             : {
     465             :   const std::string spec =
     466             :      "proc P(x:Nat)=tau.Q(true); \n"
     467             :      "     Q(x:Bool)=tau.P(1); \n"
     468           1 :      "init P(1);\n";
     469             : 
     470           1 :   run_linearisation_test_case(spec);
     471           1 : }
     472             : 
     473           2 : BOOST_AUTO_TEST_CASE(unguarded_recursion)
     474             : {
     475             :   const std::string spec =
     476             :      "proc P=P; \n"
     477           1 :      "init P;\n";
     478             : 
     479           1 :   run_linearisation_test_case(spec,false);
     480           1 : }
     481             : 
     482           2 : BOOST_AUTO_TEST_CASE(unguarded_recursion_with_parallel_operator)
     483             : {
     484             :   const std::string spec =
     485             :      "proc P=P||P; \n"
     486           1 :      "init P;\n";
     487             : 
     488           1 :   run_linearisation_test_case(spec,false);
     489           1 : }
     490             : 
     491             : #else // ndef MCRL2_SKIP_LONG_TESTS
     492             : 
     493             : BOOST_AUTO_TEST_CASE(skip_linearization_test)
     494             : {
     495             : }
     496             : 
     497             : #endif // ndef MCRL2_SKIP_LONG_TESTS
     498             : 

Generated by: LCOV version 1.14