LCOV - code coverage report
Current view: top level - data/test - rewriter_test.cpp (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 124 140 88.6 %
Date: 2024-04-21 03:44:01 Functions: 15 16 93.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Wieger Wesselink
       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 rewriter_test.cpp
      10             : /// \brief Add your file description here.
      11             : 
      12             : #define BOOST_TEST_MODULE rewriter_test
      13             : #include "mcrl2/data/detail/one_point_rule_preprocessor.h"
      14             : #include "mcrl2/data/detail/parse_substitution.h"
      15             : #include "mcrl2/data/detail/test_rewriters.h"
      16             : #include "mcrl2/data/print.h"
      17             : #include "mcrl2/data/rewriter.h"
      18             : #include "mcrl2/data/rewriters/simplify_rewriter.h"
      19             : 
      20             : #include <boost/test/included/unit_test.hpp>
      21             : 
      22             : using namespace mcrl2;
      23             : using namespace mcrl2::core;
      24             : using namespace mcrl2::data;
      25             : 
      26           1 : data::rewriter make_data_rewriter(const data_specification& data_spec)
      27             : {
      28           1 :   data::rewriter datar(data_spec);
      29           1 :   return datar;
      30             : }
      31             : 
      32             : struct A
      33             : {
      34             :   data::rewriter& r_;
      35             : 
      36           2 :   A(data::rewriter& r)
      37           2 :     : r_(r)
      38           2 :   { }
      39             : };
      40             : 
      41           1 : A make_A(data::rewriter& d)
      42             : {
      43           1 :   A result(d);
      44           1 :   return result;
      45             : }
      46             : 
      47           1 : void test1()
      48             : {
      49             :   using namespace mcrl2::data::sort_nat;
      50             : 
      51             :   std::string DATA_SPEC1 =
      52           1 :     "sort D = struct d1(Nat)?is_d1 | d2(arg2:Nat)?is_d2;\n"
      53             :     ;
      54           1 :   data_specification data = parse_data_specification(DATA_SPEC1);
      55           1 :   rewriter datar(data);
      56           2 :   variable x("x", sort_nat::nat());
      57           2 :   variable y("y", sort_nat::nat());
      58           2 :   variable z("z", sort_nat::nat());
      59           2 :   data_expression t = datar(greater(minimum(x,y), z));
      60             : 
      61           1 :   BOOST_CHECK(datar(plus(parse_data_expression("1"),
      62             :                          parse_data_expression("2"))) == datar(parse_data_expression("3")));
      63             : 
      64             :   // copy a rewriter
      65           1 :   data::rewriter datar1 = datar;
      66           1 :   t = datar1(greater(minimum(x,y), z));
      67             : 
      68             :   // rewriter as return value
      69           1 :   data::rewriter datar2 = make_data_rewriter(data);
      70           1 :   t = datar2(greater(minimum(x,y), z));
      71             : 
      72           1 :   A a(datar);
      73           1 :   data_expression qa = a.r_(t);
      74             : 
      75           1 :   A b = a;
      76           1 :   data_expression qb = b.r_(t);
      77             : 
      78           1 :   A c = make_A(datar);
      79           1 :   data_expression qc = c.r_(t);
      80           1 : }
      81             : 
      82           1 : void test2()
      83             : {
      84             :   using namespace mcrl2::data::sort_nat;
      85             : 
      86           1 :   data_specification data_spec;
      87             : 
      88           1 :   data_spec.add_context_sort(nat());
      89             : 
      90           1 :   rewriter r(data_spec);
      91           2 :   data_expression d1 = parse_data_expression("2+7");
      92           2 :   data_expression d2 = parse_data_expression("4+5");
      93           1 :   BOOST_CHECK(r(d1) == r(d2));
      94             : 
      95           2 :   data::variable_list variables = parse_variables("m, n: Pos;");
      96           1 :   data::rewriter::substitution_type sigma;
      97           1 :   sigma[atermpp::down_cast<variable>(parse_data_expression("m", variables))] = r(parse_data_expression("3"));
      98           1 :   sigma[atermpp::down_cast<variable>(parse_data_expression("n", variables))] = r(parse_data_expression("4"));
      99             : 
     100             :   // Rewrite two data expressions, and check if they are the same
     101           1 :   d1 = parse_data_expression("m+n", variables);
     102           1 :   d2 = parse_data_expression("7");
     103           1 :   BOOST_CHECK(r(d1, sigma) == r(d2));
     104           1 : }
     105             : 
     106             : template <typename Rewriter>
     107           5 : void test_expressions(Rewriter R, std::string const& expr1, std::string const& expr2, std::string const& declarations, const data_specification& data_spec, const std::string& substitution_text)
     108             : {
     109           5 :   data::rewriter::substitution_type sigma;
     110           5 :   data::detail::parse_substitution(substitution_text, sigma, data_spec);
     111           5 :   data_expression d1 = parse_data_expression(expr1, parse_variables(declarations), data_spec);
     112           5 :   data_expression d2 = parse_data_expression(expr2, parse_variables(declarations), data_spec);
     113           5 :   data_expression rd1 = R(d1, sigma);
     114           5 :   data_expression rd2 = R(d2);
     115           5 :   if (rd1 != rd2)
     116             :   {
     117           0 :     BOOST_CHECK(rd1 == rd2);
     118           0 :     std::cout << "--- failed test --- " << expr1 << " -> " << expr2 << std::endl;
     119           0 :     std::cout << "d1           " << d1 << std::endl;
     120           0 :     std::cout << "d2           " << d2 << std::endl;
     121           0 :     std::cout << "sigma\n      " << sigma << std::endl;
     122           0 :     std::cout << "R(d1, sigma) " << rd1 << std::endl;
     123           0 :     std::cout << "R(d2)        " << rd2 << std::endl;
     124             :   }
     125           5 : }
     126             : 
     127           1 : void test4()
     128             : {
     129           1 :   data_specification data_spec;
     130             : 
     131           1 :   data::rewriter R(data_spec);
     132             : 
     133           1 :   std::string expr1 = "exists b: Bool. if(c, c, b)";
     134           1 :   std::string expr2 = "exists b: Bool. if(true, true, b)";
     135           1 :   std::string sigma = "[c: Bool := true]";
     136           1 :   test_expressions(R, expr1, expr2, "c: Bool;", data_spec, sigma);
     137           1 : }
     138             : 
     139           1 : void test5() // Test set difference for finite sets.
     140             : {
     141             :   std::string DATA_SPEC1 =
     142             :     "map f,g:FSet(Bool);\n"
     143             :     "eqn f=({false}-{true})-{false};\n"
     144           1 :     "    g={};\n"
     145             :     ;
     146           1 :   data_specification data_spec = parse_data_specification(DATA_SPEC1);
     147           1 :   data::rewriter R(data_spec);
     148             : 
     149           1 :   std::string expr1 = "f";
     150           1 :   std::string expr2 = "g";
     151           1 :   std::string sigma = "[c: Bool := true]";
     152           1 :   test_expressions(R, expr1, expr2, "c: Bool;", data_spec, sigma);
     153           1 : }
     154             : 
     155           0 : void allocation_test()
     156             : {
     157           0 :   data_specification data_spec;
     158           0 :   std::shared_ptr< data::rewriter > R_heap(new data::rewriter(data_spec));
     159           0 :   data::rewriter                    R_stack(data_spec);
     160             : 
     161           0 :   R_stack(parse_data_expression("1 == 2"));
     162           0 :   R_stack(parse_data_expression("1 == 2"));
     163             : 
     164           0 :   (*R_heap)(parse_data_expression("1 == 2"));
     165           0 :   (*R_heap)(parse_data_expression("1 == 2"));
     166           0 : }
     167             : 
     168           1 : void one_point_rule_preprocessor_test()
     169             : {
     170             :   using namespace data::detail;
     171             : 
     172           1 :   test_rewriters(N(one_point_rule_preprocessor()), N(I), "!(true && false)", "!(true) || !(false)");
     173           1 :   test_rewriters(N(one_point_rule_preprocessor()), N(I), "!!b", "b");
     174           1 :   test_rewriters(N(one_point_rule_preprocessor()), N(I), "!!!!b", "b");
     175           1 :   test_rewriters(N(one_point_rule_preprocessor()), N(I), "!(b1 && b2 && b3)", "!b1 || !b2 || !b3");
     176           1 :   test_rewriters(N(one_point_rule_preprocessor()), N(I), "!(b1 || b2 || b3)", "!b1 && !b2 && !b3");
     177           1 :   test_rewriters(N(one_point_rule_preprocessor()), N(I), "!(b1 == b2)", "b1 != b2");
     178           1 :   test_rewriters(N(one_point_rule_preprocessor()), N(I), "!(b1 != b2)", "b1 == b2");
     179           1 :   test_rewriters(N(one_point_rule_preprocessor()), N(I), "!(b1 == b2 && b1 == b3)", "b1 != b2 || b1 != b3");
     180           1 :   test_rewriters(N(one_point_rule_preprocessor()), N(I), "!(b1 != b2 || b1 != b3)", "b1 == b2 && b1 == b3");
     181           1 :   test_rewriters(N(one_point_rule_preprocessor()), N(I), "!(n1 != n2 || n1 != n2 + 1)", "n1 == n2 && n1 == n2 + 1");
     182           1 : }
     183             : 
     184           1 : void simplify_rewriter_test()
     185             : {
     186             :   using data::detail::N;
     187             :   using data::detail::I;
     188             : 
     189             :   data::simplify_rewriter R;
     190           1 :   test_rewriters(N(R), N(I), "!(true && false)", "true");
     191           1 :   test_rewriters(N(R), N(I), "exists n:Nat, b:Bool. b", "exists b:Bool. b");
     192           1 :   test_rewriters(N(R), N(I), "forall b:Bool. !!b", "forall b:Bool. b");
     193           1 : }
     194             : 
     195             : // The testcase below corresponds to ticket #1426. 
     196           1 : void test_lambda_expression()
     197             : {
     198           1 :   data_specification data_spec;
     199           1 :   data::rewriter R(data_spec);
     200             : 
     201           1 :   std::string expr1 = "(lambda t: Real. true)(t) && (lambda s1: Pos, t: Real. 1 == s1)(2, u)";
     202           1 :   std::string expr2 = "false";
     203           1 :   std::string sigma = "[]";
     204           1 :   test_expressions(R, expr1, expr2, "t,u: Real;", data_spec, sigma);
     205           1 : }
     206             : 
     207             : // The testcase below corresponds to ticket #1428 which indicated
     208             : // that the generated rules for equality were erroneous. Their bound variables were equal
     209             : // f == g = forall x0,x0: Nat. f(x0, x0) == g(x0, x0)
     210           1 : void test_equality_on_functions()
     211             : {
     212             :   std::string DATA_SPEC1 =
     213             :     "map f,g:Nat#Nat->Nat;\n"
     214             :     "var x,y:Nat; \n"
     215             :     "eqn f(x,y) = x+y;\n"
     216           1 :     "    g(x,y) = x+x;\n"
     217             :     ;
     218             : 
     219           1 :   data_specification data_spec = parse_data_specification(DATA_SPEC1);
     220           1 :   data::rewriter R(data_spec);
     221             : 
     222           1 :   std::string expr1 = "f==g";
     223           1 :   std::string expr2 = "false";
     224           1 :   std::string sigma = "[]";
     225           1 :   test_expressions(R, expr1, expr2, "", data_spec, sigma);
     226           1 : }
     227             : 
     228             : // The testcase below corresponds to ticket #1461 which indicated
     229             : // that rewriting enumerated functions failed as the if function would be removed
     230             : // from the rewriters if it does not occur explicitly in the specification. 
     231           1 : void test_enumeration_of_functions()
     232             : {
     233             :   std::string DATA_SPEC1 =
     234           1 :     "sort Hat = struct black | white;"
     235             :     ;
     236             : 
     237           1 :   data_specification data_spec = parse_data_specification(DATA_SPEC1);
     238             :   // For this test it is essential that unnecessary equations are removed. 
     239           2 :   data::rewriter R(data_spec,used_data_equation_selector(data_spec,std::set<function_symbol>()));
     240             : 
     241           1 :   std::string expr1 = "exists f:Hat->Hat.f(black)!=f(white)";
     242           1 :   std::string expr2 = "true";
     243           1 :   std::string sigma = "[]";
     244           1 :   test_expressions(R, expr1, expr2, "", data_spec, sigma);
     245           1 : }
     246             : 
     247           2 : BOOST_AUTO_TEST_CASE(test_main)
     248             : {
     249           1 :   test1();
     250           1 :   test2();
     251           1 :   test4();
     252           1 :   test5();
     253           1 :   one_point_rule_preprocessor_test();
     254           1 :   simplify_rewriter_test();
     255           1 :   test_lambda_expression();
     256           1 :   test_equality_on_functions();
     257           1 :   test_enumeration_of_functions();
     258           1 : }

Generated by: LCOV version 1.14