The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
test_formula_core.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2016
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-test"
16 
17 #include <boost/test/unit_test.hpp>
18 
19 #include <ctime>
20 
21 #include "formula/formula.hpp"
22 #include "formula/callable.hpp"
23 
24 using namespace game_logic;
25 
26 class mock_char : public formula_callable {
27  variant get_value(const std::string& key) const {
28  if(key == "strength") {
29  return variant(15);
30  } else if(key == "agility") {
31  return variant(12);
32  }
33 
34  return variant(10);
35  }
36 };
37 
38 class mock_party : public formula_callable {
39  variant get_value(const std::string& key) const {
40  if(key == "members") {
41  i_[0].add("strength",variant(12));
42  i_[1].add("strength",variant(16));
43  i_[2].add("strength",variant(14));
44  std::vector<variant> members;
45  for(int n = 0; n != 3; ++n) {
46  members.push_back(variant(&i_[n]));
47  }
48 
49  return variant(&members);
50  } else if(key == "char") {
51  return variant(&c_);
52  } else {
53  return variant(0);
54  }
55  }
56 
59 
60 public:
62  c_.add_ref();
63  i_[0].add_ref();
64  i_[1].add_ref();
65  i_[2].add_ref();
66  }
67 };
68 
69 BOOST_AUTO_TEST_SUITE(formula_core)
70 
73 
74 BOOST_AUTO_TEST_CASE(test_formula_basic_arithmetic)
75 {
76  BOOST_CHECK_EQUAL(formula("strength").evaluate(c).as_int(), 15);
77  BOOST_CHECK_EQUAL(formula("17").evaluate().as_int(), 17);
78 
79  BOOST_CHECK_EQUAL(formula("strength/2 + agility").evaluate(c).as_int(), 19);
80  BOOST_CHECK_EQUAL(formula("(strength+agility)/2").evaluate(c).as_int(), 13);
81 
82  BOOST_CHECK_EQUAL(formula("20 % 3").evaluate().as_int(), 2);
83  BOOST_CHECK_EQUAL(formula("19.5 % 3").evaluate().as_decimal(),
84  static_cast<int>(1000.0 * 1.5));
85 
86  BOOST_CHECK_EQUAL(formula("-5").evaluate().as_int(), -5);
87 
88  BOOST_CHECK_EQUAL(formula("4^2").evaluate().as_int(), 16);
89  BOOST_CHECK_EQUAL(formula("2+3^3").evaluate().as_int(), 29);
90  BOOST_CHECK_EQUAL(formula("2*3^3+2").evaluate().as_int(), 56);
91  BOOST_CHECK_EQUAL(formula("2^3^2").evaluate().as_int(), 512);
92  BOOST_CHECK_EQUAL(formula("9^3").evaluate().as_int(), 729);
93  BOOST_CHECK(formula("(-2)^0.5").evaluate().is_null());
94 }
95 
96 BOOST_AUTO_TEST_CASE(test_formula_basic_logic)
97 {
98  BOOST_CHECK_EQUAL(formula("strength > 12").evaluate(c).as_int(), 1);
99  BOOST_CHECK_EQUAL(formula("strength > 18").evaluate(c).as_int(), 0);
100 
101  BOOST_CHECK_EQUAL(formula("if(strength > 12, 7, 2)").evaluate(c).as_int(), 7);
102  BOOST_CHECK_EQUAL(formula("if(strength > 18, 7, 2)").evaluate(c).as_int(), 2);
103 
104  BOOST_CHECK_EQUAL(formula("2 and 1").evaluate().as_int(), 1);
105  BOOST_CHECK_EQUAL(formula("2 and 0").evaluate().as_int(), 0);
106  BOOST_CHECK_EQUAL(formula("2 or 0").evaluate().as_int(), 2);
107 
108  BOOST_CHECK_EQUAL(formula("not 5").evaluate().as_int(), 0);
109  BOOST_CHECK_EQUAL(formula("not 0").evaluate().as_int(), 1);
110 }
111 
112 BOOST_AUTO_TEST_CASE(test_formula_callable)
113 {
114  // These are just misc tests that were in the original unit tests
115  // I wasn't sure how to classify them.
116  BOOST_CHECK_EQUAL(formula("char.strength").evaluate(p).as_int(), 15);
117  BOOST_CHECK_EQUAL(formula("choose(members,strength).strength").evaluate(p).as_int(), 16);
118 
119  BOOST_CHECK_EQUAL(formula("char.sum([strength, agility, intelligence])").evaluate(p).as_int(), 37);
120 }
121 
122 BOOST_AUTO_TEST_CASE(test_formula_where_clause)
123 {
124  BOOST_CHECK_EQUAL(formula("x*5 where x=1").evaluate().as_int(), 5);
125  BOOST_CHECK_EQUAL(formula("x*5 where x=2").evaluate().as_int(), 10);
126 
127  BOOST_CHECK_EQUAL(formula("x*(a*b where a=2,b=1) where x=5").evaluate().as_int(), 10);
128  BOOST_CHECK_EQUAL(formula("char.strength * ability where ability=3").evaluate(p).as_int(), 45);
129 }
130 
131 BOOST_AUTO_TEST_CASE(test_formula_strings)
132 {
133  BOOST_CHECK_EQUAL(formula("'abcd' = 'abcd'").evaluate().as_bool(), true);
134  BOOST_CHECK_EQUAL(formula("'abcd' = 'acd'").evaluate().as_bool(), false);
135 
136  BOOST_CHECK_EQUAL(formula("'ab' .. 'cd'").evaluate().as_string(), "abcd");
137 
138  BOOST_CHECK_EQUAL(formula("'strength, agility: [strength], [agility]'").evaluate(c).as_string(),
139  "strength, agility: 15, 12");
140 
141  BOOST_CHECK_EQUAL(formula("'String with [']quotes['] and [(]brackets[)]!'").evaluate().as_string(),
142  "String with 'quotes' and [brackets]!");
143  BOOST_CHECK_EQUAL(formula("'String with ['embedded ' .. 'string']!'").evaluate().as_string(),
144  "String with embedded string!");
145 }
146 
147 BOOST_AUTO_TEST_CASE(test_formula_dice) {
148  const int dice_roll = formula("3d6").evaluate().as_int();
149  assert(dice_roll >= 3 && dice_roll <= 18);
150 }
151 
152 BOOST_AUTO_TEST_CASE(test_formula_containers) {
153  variant myarray = formula("[1,2,3]").evaluate();
154  BOOST_CHECK_EQUAL(myarray.num_elements(), 3);
155  BOOST_CHECK_EQUAL(myarray[0].as_int(), 1);
156  BOOST_CHECK_EQUAL(myarray[1].as_int(), 2);
157  BOOST_CHECK_EQUAL(myarray[2].as_int(), 3);
158 
159  variant mydict = formula("['foo' -> 5, 'bar' ->7]").evaluate();
160  BOOST_CHECK_EQUAL(mydict.num_elements(), 2);
161  BOOST_CHECK_EQUAL(mydict[variant("foo")].as_int(), 5);
162  BOOST_CHECK_EQUAL(mydict[variant("bar")].as_int(), 7);
163 
164  variant myrange = formula("-2~2").evaluate();
165  BOOST_CHECK_EQUAL(myrange.num_elements(), 5);
166  BOOST_CHECK_EQUAL(myrange[0].as_int(), -2);
167  BOOST_CHECK_EQUAL(myrange[1].as_int(), -1);
168  BOOST_CHECK_EQUAL(myrange[2].as_int(), 0);
169  BOOST_CHECK_EQUAL(myrange[3].as_int(), 1);
170  BOOST_CHECK_EQUAL(myrange[4].as_int(), 2);
171 
172  variant myslice = formula("(10~20)[[1,3,7,9]]").evaluate();
173  BOOST_CHECK_EQUAL(myslice.num_elements(), 4);
174  BOOST_CHECK_EQUAL(myslice[0].as_int(), 11);
175  BOOST_CHECK_EQUAL(myslice[1].as_int(), 13);
176  BOOST_CHECK_EQUAL(myslice[2].as_int(), 17);
177  BOOST_CHECK_EQUAL(myslice[3].as_int(), 19);
178 }
179 
180 BOOST_AUTO_TEST_SUITE_END()
size_t num_elements() const
Definition: variant.cpp:526
BOOST_AUTO_TEST_CASE(test_formula_basic_arithmetic)
variant get_value(const std::string &key) const
const GLfloat * c
Definition: glew.h:12741
BOOST_AUTO_TEST_SUITE(test_map_location)
variant get_value(const std::string &key) const
int as_int() const
Definition: variant.cpp:558
GLfloat GLfloat p
Definition: glew.h:12766
static variant evaluate(const const_formula_ptr &f, const formula_callable &variables, formula_debugger *fdb=nullptr, variant default_res=variant(0))
Definition: formula.hpp:31
int i_
Definition: formula.cpp:667
GLclampd n
Definition: glew.h:5903
GLsizei const GLcharARB ** string
Definition: glew.h:4503