LCOV - code coverage report
Current view: top level - buildbot/coverage/build/test/unit/options - options_black.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 130 139 93.5 %
Date: 2026-01-31 12:26:27 Functions: 22 23 95.7 %
Branches: 86 132 65.2 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Gereon Kremer, Andrew Reynolds, Aina Niemetz
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2025 by the authors listed in the file AUTHORS
       8                 :            :  * in the top-level source directory and their institutional affiliations.
       9                 :            :  * All rights reserved.  See the file COPYING in the top-level source
      10                 :            :  * directory for licensing information.
      11                 :            :  * ****************************************************************************
      12                 :            :  *
      13                 :            :  * Black box testing of the Solver class of the  C++ API.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include <cvc5/cvc5_types.h>
      17                 :            : 
      18                 :            : #include <algorithm>
      19                 :            : #include <limits>
      20                 :            : 
      21                 :            : #include "options/option_exception.h"
      22                 :            : #include "options/options_public.h"
      23                 :            : #include "test_api.h"
      24                 :            : 
      25                 :            : namespace cvc5::internal {
      26                 :            : 
      27                 :            : namespace test {
      28                 :            : 
      29                 :            : template <class... Ts>
      30                 :            : struct overloaded : Ts...
      31                 :            : {
      32                 :            :   using Ts::operator()...;
      33                 :            : };
      34                 :            : template <class... Ts>
      35                 :            : overloaded(Ts...) -> overloaded<Ts...>;
      36                 :            : 
      37                 :            : class TestBlackOptions : public TestApi
      38                 :            : {
      39                 :            :  public:
      40                 :            :   /**
      41                 :            :    * Tests setting options for option "name", including error values.
      42                 :            :    */
      43                 :      27201 :   void testSetOption(const std::string& name)
      44                 :            :   {
      45                 :      54310 :     auto info = d_solver->getOptionInfo(name);
      46                 :            : 
      47                 :            :     try
      48                 :            :     {
      49                 :      27201 :       std::visit(
      50                 :      27201 :           overloaded{
      51                 :       1482 :               [this, &name](const OptionInfo::VoidInfo& v) {
      52                 :       1447 :                 d_solver->setOption(name, "");
      53                 :         35 :               },
      54                 :      73816 :               [this, &name](const OptionInfo::ValueInfo<bool>& v) {
      55                 :      18454 :                 d_solver->setOption(name, "false");
      56                 :      18454 :                 d_solver->setOption(name, "true");
      57                 :      18454 :               },
      58                 :        294 :               [this, &name](const OptionInfo::ValueInfo<std::string>& v) {
      59                 :        147 :                 d_solver->setOption(name, "foo");
      60                 :        147 :               },
      61                 :       7646 :               [this, &name](const OptionInfo::NumberInfo<int64_t>& v) {
      62                 :       1402 :                 std::pair<int64_t, int64_t> range{
      63                 :            :                     std::numeric_limits<int64_t>::min(),
      64                 :            :                     std::numeric_limits<int64_t>::max()};
      65         [ +  + ]:       1402 :                 if (v.minimum)
      66                 :            :                 {
      67 [ +  - ][ +  - ]:        477 :                   EXPECT_THROW(
                 [ -  + ]
      68                 :            :                       d_solver->setOption(name, std::to_string(*v.minimum - 1)),
      69                 :            :                       CVC5ApiOptionException);
      70 [ +  - ][ +  - ]:        159 :                   EXPECT_NO_THROW(
      71                 :            :                       d_solver->setOption(name, std::to_string(*v.minimum)));
      72                 :        159 :                   range.first = *v.minimum;
      73                 :            :                 }
      74         [ -  + ]:       1402 :                 if (v.maximum)
      75                 :            :                 {
      76                 :          0 :                   EXPECT_THROW(
      77                 :            :                       d_solver->setOption(name, std::to_string(*v.maximum + 1)),
      78                 :            :                       CVC5ApiOptionException);
      79                 :          0 :                   EXPECT_NO_THROW(
      80                 :            :                       d_solver->setOption(name, std::to_string(*v.maximum)));
      81                 :          0 :                   range.second = *v.maximum;
      82                 :            :                 }
      83 [ +  - ][ +  - ]:       1402 :                 EXPECT_NO_THROW(d_solver->setOption(
      84                 :            :                     name, std::to_string((range.first + range.second) / 2)));
      85 [ +  - ][ +  - ]:       5608 :                 EXPECT_THROW(d_solver->setOption(name, "0123abc"),
                 [ -  + ]
      86                 :            :                              CVC5ApiOptionException);
      87                 :       1402 :               },
      88                 :      13258 :               [this, &name](const OptionInfo::NumberInfo<uint64_t>& v) {
      89                 :       1718 :                 std::pair<uint64_t, uint64_t> range{
      90                 :            :                     std::numeric_limits<uint64_t>::min(),
      91                 :            :                     std::numeric_limits<uint64_t>::max()};
      92 [ +  - ][ +  - ]:       6872 :                 EXPECT_THROW(d_solver->setOption(name, "-1"),
                 [ -  + ]
      93                 :            :                              CVC5ApiOptionException);
      94         [ +  + ]:       1718 :                 if (v.minimum)
      95                 :            :                 {
      96 [ +  - ][ +  - ]:        267 :                   EXPECT_THROW(
                 [ -  + ]
      97                 :            :                       d_solver->setOption(name, std::to_string(*v.minimum - 1)),
      98                 :            :                       CVC5ApiOptionException);
      99 [ +  - ][ +  - ]:         89 :                   EXPECT_NO_THROW(
     100                 :            :                       d_solver->setOption(name, std::to_string(*v.minimum)));
     101                 :         89 :                   range.first = *v.minimum;
     102                 :            :                 }
     103         [ +  + ]:       1718 :                 if (v.maximum)
     104                 :            :                 {
     105 [ +  - ][ +  - ]:        657 :                   EXPECT_THROW(
                 [ -  + ]
     106                 :            :                       d_solver->setOption(name, std::to_string(*v.maximum + 1)),
     107                 :            :                       CVC5ApiOptionException);
     108 [ +  - ][ +  - ]:        219 :                   EXPECT_NO_THROW(
     109                 :            :                       d_solver->setOption(name, std::to_string(*v.maximum)));
     110                 :        219 :                   range.second = *v.maximum;
     111                 :            :                 }
     112 [ +  - ][ +  - ]:       1718 :                 EXPECT_NO_THROW(d_solver->setOption(
     113                 :            :                     name, std::to_string((range.first + range.second) / 2)));
     114 [ +  - ][ +  - ]:       6872 :                 EXPECT_THROW(d_solver->setOption(name, "0123abc"),
                 [ -  + ]
     115                 :            :                              CVC5ApiOptionException);
     116                 :       1718 :               },
     117                 :       2537 :               [this, &name](const OptionInfo::NumberInfo<double>& v) {
     118                 :        279 :                 std::pair<double, double> range{
     119                 :            :                     std::numeric_limits<double>::min(),
     120                 :            :                     std::numeric_limits<double>::max()};
     121         [ +  + ]:        279 :                 if (v.minimum)
     122                 :            :                 {
     123 [ +  - ][ +  - ]:        690 :                   EXPECT_THROW(
                 [ -  + ]
     124                 :            :                       d_solver->setOption(name, std::to_string(*v.minimum - 1)),
     125                 :            :                       CVC5ApiOptionException);
     126 [ +  - ][ +  - ]:        230 :                   EXPECT_NO_THROW(
     127                 :            :                       d_solver->setOption(name, std::to_string(*v.minimum)));
     128                 :        230 :                   range.first = *v.minimum;
     129                 :            :                 }
     130         [ +  + ]:        279 :                 if (v.maximum)
     131                 :            :                 {
     132 [ +  - ][ +  - ]:        585 :                   EXPECT_THROW(
                 [ -  + ]
     133                 :            :                       d_solver->setOption(name, std::to_string(*v.maximum + 1)),
     134                 :            :                       CVC5ApiOptionException);
     135 [ +  - ][ +  - ]:        195 :                   EXPECT_NO_THROW(
     136                 :            :                       d_solver->setOption(name, std::to_string(*v.maximum)));
     137                 :        195 :                   range.second = *v.maximum;
     138                 :            :                 }
     139 [ +  - ][ +  - ]:        279 :                 EXPECT_NO_THROW(d_solver->setOption(
     140                 :            :                     name, std::to_string((range.first + range.second) / 2)));
     141                 :        279 :               },
     142                 :      69696 :               [this, &name](const OptionInfo::ModeInfo& v) {
     143 [ +  - ][ +  - ]:      17840 :                 EXPECT_THROW(d_solver->setOption(name, "foobarbaz"),
                 [ -  + ]
     144                 :            :                              CVC5ApiOptionException);
     145         [ +  + ]:      18448 :                 for (const auto& m : v.modes)
     146                 :            :                 {
     147                 :      14078 :                   d_solver->setOption(name, m);
     148         [ -  + ]:      27976 :                   EXPECT_EQ(d_solver->getOption(name), m);
     149                 :            :                 }
     150                 :       4370 :                 EXPECT_DEATH(d_solver->setOption(name, "help"), "");
     151                 :       4278 :               },
     152                 :            :           },
     153                 :            :           info.valueInfo);
     154                 :            :     }
     155                 :        796 :     catch (const CVC5ApiOptionException&)
     156                 :            :     {
     157                 :            :     }
     158                 :      27109 :   }
     159                 :            :   /**
     160                 :            :    * Sets a single valid option for option "name".
     161                 :            :    */
     162                 :         59 :   void testSetOptionOnce(const std::string& name)
     163                 :            :   {
     164                 :        118 :     auto info = d_solver->getOptionInfo(name);
     165                 :            : 
     166                 :            :     try
     167                 :            :     {
     168                 :         59 :       std::visit(
     169                 :         59 :           overloaded{
     170                 :         14 :               [this, &name](const OptionInfo::VoidInfo& v) {
     171                 :         14 :                 d_solver->setOption(name, "");
     172                 :          0 :               },
     173                 :         68 :               [this, &name](const OptionInfo::ValueInfo<bool>& v) {
     174                 :         34 :                 d_solver->setOption(name, "false");
     175                 :         34 :               },
     176                 :          4 :               [this, &name](const OptionInfo::ValueInfo<std::string>& v) {
     177                 :          2 :                 d_solver->setOption(name, "foo");
     178                 :          2 :               },
     179                 :          6 :               [this, &name](const OptionInfo::NumberInfo<int64_t>& v) {
     180                 :          3 :                 std::pair<int64_t, int64_t> range{
     181                 :            :                     std::numeric_limits<int64_t>::min(),
     182                 :            :                     std::numeric_limits<int64_t>::max()};
     183                 :          6 :                 d_solver->setOption(
     184                 :          6 :                     name, std::to_string((range.first + range.second) / 2));
     185                 :          3 :               },
     186                 :         14 :               [this, &name](const OptionInfo::NumberInfo<uint64_t>& v) {
     187                 :          7 :                 std::pair<uint64_t, uint64_t> range{
     188                 :            :                     std::numeric_limits<uint64_t>::min(),
     189                 :            :                     std::numeric_limits<uint64_t>::max()};
     190                 :         14 :                 d_solver->setOption(
     191                 :         14 :                     name, std::to_string((range.first + range.second) / 2));
     192                 :          7 :               },
     193                 :          0 :               [this, &name](const OptionInfo::NumberInfo<double>& v) {
     194                 :          0 :                 std::pair<double, double> range{
     195                 :            :                     std::numeric_limits<double>::min(),
     196                 :            :                     std::numeric_limits<double>::max()};
     197                 :          0 :                 d_solver->setOption(
     198                 :          0 :                     name, std::to_string((range.first + range.second) / 2));
     199                 :          0 :               },
     200                 :         18 :               [this, &name](const OptionInfo::ModeInfo& v) {
     201         [ +  - ]:          6 :                 if (!v.modes.empty())
     202                 :            :                 {
     203                 :          6 :                   d_solver->setOption(name, v.modes[0]);
     204                 :            :                 }
     205                 :          6 :               },
     206                 :            :           },
     207                 :            :           info.valueInfo);
     208                 :            :     }
     209                 :          7 :     catch (const CVC5ApiOptionException&)
     210                 :            :     {
     211                 :            :     }
     212                 :         59 :   }
     213                 :            : };
     214                 :            : 
     215                 :        186 : TEST_F(TestBlackOptions, set)
     216                 :            : {
     217                 :            :   const std::set<std::string> muted{"copyright",
     218                 :            :                                     "help",
     219                 :            :                                     "show-config",
     220                 :            :                                     "show-debug-tags",
     221                 :            :                                     "show-trace-tags",
     222                 :        838 :                                     "version"};
     223         [ +  + ]:      27237 :   for (const auto& name : options::getNames())
     224                 :            :   {
     225         [ +  + ]:      27236 :     if (name == "safe-mode")
     226                 :            :     {
     227                 :            :       // don't test safe-mode here, since it will restrict the set of options
     228                 :            :       // that can be set afterwards.
     229                 :         35 :       continue;
     230                 :            :     }
     231         [ +  + ]:      27201 :     if (muted.count(name))
     232                 :            :     {
     233                 :        223 :       testing::internal::CaptureStdout();
     234                 :            :     }
     235                 :      27201 :     testSetOption(name);
     236         [ +  + ]:      27109 :     if (muted.count(name))
     237                 :            :     {
     238                 :        223 :       testing::internal::GetCapturedStdout();
     239                 :            :     }
     240                 :            :   }
     241                 :          1 : }
     242                 :            : 
     243                 :          2 : TEST_F(TestBlackOptions, setSafe)
     244                 :            : {
     245                 :            :   const std::set<std::string> muted{"copyright",
     246                 :            :                                     "help",
     247                 :            :                                     "show-config",
     248                 :            :                                     "show-debug-tags",
     249                 :            :                                     "show-trace-tags",
     250                 :         10 :                                     "version"};
     251                 :            :   // set safe options to true
     252                 :          1 :   d_solver->setOption("safe-mode", "safe");
     253                 :          1 :   bool alreadySetRegular = false;
     254         [ +  + ]:        530 :   for (const auto& name : options::getNames())
     255                 :            :   {
     256                 :        529 :     auto info = d_solver->getOptionInfo(name);
     257                 :            :     // skip if an expert option or has an supported feature
     258                 :       1401 :     if (info.category == cvc5::modes::OptionCategory::EXPERT
     259 [ +  + ][ +  + ]:        529 :         || !info.noSupports.empty())
                 [ +  + ]
     260                 :            :     {
     261                 :        343 :       continue;
     262                 :            :     }
     263         [ +  + ]:        186 :     if (info.category == cvc5::modes::OptionCategory::REGULAR)
     264                 :            :     {
     265         [ +  + ]:        128 :       if (alreadySetRegular)
     266                 :            :       {
     267                 :            :         // skip if already set a regular option
     268                 :        127 :         continue;
     269                 :            :       }
     270                 :          1 :       alreadySetRegular = true;
     271                 :            :     }
     272         [ +  + ]:         59 :     if (muted.count(name))
     273                 :            :     {
     274                 :          4 :       testing::internal::CaptureStdout();
     275                 :            :     }
     276                 :            :     // set the option once
     277                 :         59 :     testSetOptionOnce(name);
     278         [ +  + ]:         59 :     if (muted.count(name))
     279                 :            :     {
     280                 :          4 :       testing::internal::GetCapturedStdout();
     281                 :            :     }
     282                 :            :   }
     283                 :          1 : }
     284                 :            : 
     285                 :          2 : TEST_F(TestBlackOptions, getOptionInfoBenchmark)
     286                 :            : {
     287                 :          2 :   auto names = options::getNames();
     288                 :            :   std::unordered_set<std::string> ignore = {
     289                 :            :     "output",
     290                 :            :     "quiet",
     291                 :            :     "rweight",
     292                 :            :     "trace",
     293                 :            :     "verbose",
     294                 :          9 :   };
     295                 :        529 :   auto end = std::remove_if(names.begin(), names.end(), [&](const auto& i){
     296                 :        529 :       return ignore.count(i);
     297                 :          1 :   });
     298                 :          1 :   names.erase(end, names.end());
     299                 :          1 :   size_t ct = 0;
     300         [ +  + ]:       1001 :   for (size_t i = 0; i < 1000; ++i)
     301                 :            :   {
     302         [ +  + ]:     525000 :     for (const auto& name : names)
     303                 :            :     {
     304                 :     524000 :       ct += d_solver->getOption(name).size();
     305                 :            :     }
     306                 :            :   }
     307                 :          1 :   std::cout << ct << std::endl;
     308                 :          1 : }
     309                 :            : 
     310                 :            : }  // namespace test
     311                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14