Transfer original formula unit tests to Boost framework

In the process, I have corrected a few tests and added a few extras
This commit is contained in:
Celtic Minstrel 2016-03-11 15:51:21 -05:00
parent e78b5d7baf
commit f6be40bb71
6 changed files with 196 additions and 93 deletions

View File

@ -158,6 +158,7 @@
91DCA68A1C9066CC0030F8D0 /* unit_preview_pane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91DCA6871C9066CC0030F8D0 /* unit_preview_pane.cpp */; };
91DCA68D1C9066EC0030F8D0 /* unit_recruit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91DCA68B1C9066EC0030F8D0 /* unit_recruit.cpp */; };
91DCA68E1C9066EC0030F8D0 /* unit_recruit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91DCA68B1C9066EC0030F8D0 /* unit_recruit.cpp */; };
91DCA6901C9360610030F8D0 /* test_formula_core.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91DCA68F1C9360610030F8D0 /* test_formula_core.cpp */; };
91ECD5D21BA11A5200B25CF1 /* unit_creator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91ECD5D01BA11A5200B25CF1 /* unit_creator.cpp */; };
91ECD5D51BA11A6400B25CF1 /* mp_replay_controller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91ECD5D31BA11A6400B25CF1 /* mp_replay_controller.cpp */; };
91F462841C71139C0050A9C9 /* preferences_dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91F462821C71139B0050A9C9 /* preferences_dialog.cpp */; };
@ -1493,6 +1494,7 @@
91DCA6881C9066CC0030F8D0 /* unit_preview_pane.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = unit_preview_pane.hpp; sourceTree = "<group>"; };
91DCA68B1C9066EC0030F8D0 /* unit_recruit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unit_recruit.cpp; sourceTree = "<group>"; };
91DCA68C1C9066EC0030F8D0 /* unit_recruit.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = unit_recruit.hpp; sourceTree = "<group>"; };
91DCA68F1C9360610030F8D0 /* test_formula_core.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_formula_core.cpp; sourceTree = "<group>"; };
91ECD5D01BA11A5200B25CF1 /* unit_creator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unit_creator.cpp; sourceTree = "<group>"; };
91ECD5D11BA11A5200B25CF1 /* unit_creator.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = unit_creator.hpp; sourceTree = "<group>"; };
91ECD5D31BA11A6400B25CF1 /* mp_replay_controller.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mp_replay_controller.cpp; sourceTree = "<group>"; };
@ -3835,6 +3837,7 @@
B597C4A90FACD42E00CE81F5 /* main.cpp */,
B597C4A80FACD42E00CE81F5 /* test_config_cache.cpp */,
B597C4A70FACD42E00CE81F5 /* test_formula_ai.cpp */,
91DCA68F1C9360610030F8D0 /* test_formula_core.cpp */,
B597C4AD0FACD42E00CE81F5 /* test_lexical_cast.cpp */,
B597C4AC0FACD42E00CE81F5 /* test_network_worker.cpp */,
B597C4AA0FACD42E00CE81F5 /* test_serialization.cpp */,
@ -5555,6 +5558,7 @@
91DCA6861C9066A60030F8D0 /* unit_preview_pane.cpp in Sources */,
91DCA68A1C9066CC0030F8D0 /* unit_preview_pane.cpp in Sources */,
91DCA68E1C9066EC0030F8D0 /* unit_recruit.cpp in Sources */,
91DCA6901C9360610030F8D0 /* test_formula_core.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -1460,6 +1460,7 @@ if(ENABLE_TESTS)
tests/test_config_cache.cpp
tests/test_filesystem.cpp
tests/test_formula_ai.cpp
tests/test_formula_core.cpp
tests/test_formula_function.cpp
tests/test_image_modifications.cpp
tests/test_lexical_cast.cpp

View File

@ -772,6 +772,7 @@ test_sources = Split("""
tests/test_config.cpp
tests/test_filesystem.cpp
tests/test_formula_ai.cpp
tests/test_formula_core.cpp
tests/test_formula_function.cpp
tests/test_image_modifications.cpp
tests/test_lexical_cast.cpp

View File

@ -1261,96 +1261,3 @@ formula_error::formula_error(const std::string& type, const std::string& formula
}
#ifdef UNIT_TEST_FORMULA
using namespace game_logic;
class mock_char : public formula_callable {
variant get_value(const std::string& key) const {
if(key == "strength") {
return variant(15);
} else if(key == "agility") {
return variant(12);
}
return variant(10);
}
};
class mock_party : public formula_callable {
variant get_value(const std::string& key) const {
if(key == "members") {
i_[0].add("strength",variant(12));
i_[1].add("strength",variant(16));
i_[2].add("strength",variant(14));
std::vector<variant> members;
for(int n = 0; n != 3; ++n) {
members.push_back(variant(&i_[n]));
}
return variant(&members);
} else if(key == "char") {
return variant(&c_);
} else {
return variant(0);
}
}
mock_char c_;
mutable map_formula_callable i_[3];
};
#include <time.h>
int main()
{
srand(time(NULL));
try {
mock_char c;
mock_party p;
assert(formula("strength").execute(c).as_int() == 15);
assert(formula("17").execute(c).as_int() == 17);
assert(formula("strength/2 + agility").execute(c).as_int() == 19);
assert(formula("(strength+agility)/2").execute(c).as_int() == 13);
assert(formula("strength > 12").execute(c).as_int() == 1);
assert(formula("strength > 18").execute(c).as_int() == 0);
assert(formula("if(strength > 12, 7, 2)").execute(c).as_int() == 7);
assert(formula("if(strength > 18, 7, 2)").execute(c).as_int() == 2);
assert(formula("2 and 1").execute(c).as_int() == 1);
assert(formula("2 and 0").execute(c).as_int() == 0);
assert(formula("2 or 0").execute(c).as_int() == 1);
assert(formula("-5").execute(c).as_int() == -5);
assert(formula("not 5").execute(c).as_int() == 0);
assert(formula("not 0").execute(c).as_int() == 1);
assert(formula("abs(5)").execute(c).as_int() == 5);
assert(formula("abs(-5)").execute(c).as_int() == 5);
assert(formula("min(3,5)").execute(c).as_int() == 3);
assert(formula("min(5,2)").execute(c).as_int() == 2);
assert(formula("max(3,5)").execute(c).as_int() == 5);
assert(formula("max(5,2)").execute(c).as_int() == 5);
assert(formula("max(4,5,[2,18,7])").execute(c).as_int() == 18);
assert(formula("char.strength").execute(p).as_int() == 15);
assert(formula("choose(members,strength).strength").execute(p).as_int() == 16);
assert(formula("4^2").execute().as_int() == 16);
assert(formula("2+3^3").execute().as_int() == 29);
assert(formula("2*3^3+2").execute().as_int() == 56);
assert(formula("9^3").execute().as_int() == 729);
assert(formula("x*5 where x=1").execute().as_int() == 5);
assert(formula("x*(a*b where a=2,b=1) where x=5").execute().as_int() == 10);
assert(formula("char.strength * ability where ability=3").execute(p).as_int() == 45);
assert(formula("'abcd' = 'abcd'").execute(p).as_bool() == true);
assert(formula("'abcd' = 'acd'").execute(p).as_bool() == false);
assert(formula("'strength, agility: {strength}, {agility}'").execute(c).as_string() ==
"strength, agility: 15, 12");
const int dice_roll = formula("3d6").execute().as_int();
assert(dice_roll >= 3 && dice_roll <= 18);
variant myarray = formula("[1,2,3]").execute();
assert(myarray.num_elements() == 3);
assert(myarray[0].as_int() == 1);
assert(myarray[1].as_int() == 2);
assert(myarray[2].as_int() == 3);
} catch(formula_error& e) {
std::cerr << "parse error\n";
}
}
#endif

View File

@ -0,0 +1,175 @@
/*
Copyright (C) 2008 - 2016
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#define GETTEXT_DOMAIN "wesnoth-test"
#include <boost/test/unit_test.hpp>
#include <ctime>
#include "formula.hpp"
#include "formula_callable.hpp"
using namespace game_logic;
class mock_char : public formula_callable {
variant get_value(const std::string& key) const {
if(key == "strength") {
return variant(15);
} else if(key == "agility") {
return variant(12);
}
return variant(10);
}
};
class mock_party : public formula_callable {
variant get_value(const std::string& key) const {
if(key == "members") {
i_[0].add("strength",variant(12));
i_[1].add("strength",variant(16));
i_[2].add("strength",variant(14));
std::vector<variant> members;
for(int n = 0; n != 3; ++n) {
members.push_back(variant(&i_[n]));
}
return variant(&members);
} else if(key == "char") {
return variant(&c_);
} else {
return variant(0);
}
}
mock_char c_;
mutable map_formula_callable i_[3];
public:
mock_party() {
c_.add_ref();
i_[0].add_ref();
i_[1].add_ref();
i_[2].add_ref();
}
};
BOOST_AUTO_TEST_SUITE(formula_core)
mock_char c;
mock_party p;
BOOST_AUTO_TEST_CASE(test_formula_basic_arithmetic)
{
BOOST_CHECK_EQUAL(formula("strength").evaluate(c).as_int(), 15);
BOOST_CHECK_EQUAL(formula("17").evaluate().as_int(), 17);
BOOST_CHECK_EQUAL(formula("strength/2 + agility").evaluate(c).as_int(), 19);
BOOST_CHECK_EQUAL(formula("(strength+agility)/2").evaluate(c).as_int(), 13);
BOOST_CHECK_EQUAL(formula("20 % 3").evaluate().as_int(), 2);
BOOST_CHECK_EQUAL(formula("19.5 % 3").evaluate().as_decimal(),
static_cast<int>(1000.0 * 1.5));
BOOST_CHECK_EQUAL(formula("-5").evaluate().as_int(), -5);
BOOST_CHECK_EQUAL(formula("4^2").evaluate().as_int(), 16);
BOOST_CHECK_EQUAL(formula("2+3^3").evaluate().as_int(), 29);
BOOST_CHECK_EQUAL(formula("2*3^3+2").evaluate().as_int(), 56);
BOOST_CHECK_EQUAL(formula("2^3^2").evaluate().as_int(), 512);
BOOST_CHECK_EQUAL(formula("9^3").evaluate().as_int(), 729);
BOOST_CHECK(formula("(-2)^0.5").evaluate().is_null());
}
BOOST_AUTO_TEST_CASE(test_formula_basic_logic)
{
BOOST_CHECK_EQUAL(formula("strength > 12").evaluate(c).as_int(), 1);
BOOST_CHECK_EQUAL(formula("strength > 18").evaluate(c).as_int(), 0);
BOOST_CHECK_EQUAL(formula("if(strength > 12, 7, 2)").evaluate(c).as_int(), 7);
BOOST_CHECK_EQUAL(formula("if(strength > 18, 7, 2)").evaluate(c).as_int(), 2);
BOOST_CHECK_EQUAL(formula("2 and 1").evaluate().as_int(), 1);
BOOST_CHECK_EQUAL(formula("2 and 0").evaluate().as_int(), 0);
BOOST_CHECK_EQUAL(formula("2 or 0").evaluate().as_int(), 2);
BOOST_CHECK_EQUAL(formula("not 5").evaluate().as_int(), 0);
BOOST_CHECK_EQUAL(formula("not 0").evaluate().as_int(), 1);
}
BOOST_AUTO_TEST_CASE(test_formula_callable)
{
// These are just misc tests that were in the original unit tests
// I wasn't sure how to classify them.
BOOST_CHECK_EQUAL(formula("char.strength").evaluate(p).as_int(), 15);
BOOST_CHECK_EQUAL(formula("choose(members,strength).strength").evaluate(p).as_int(), 16);
BOOST_CHECK_EQUAL(formula("char.sum([strength, agility, intelligence])").evaluate(p).as_int(), 37);
}
BOOST_AUTO_TEST_CASE(test_formula_where_clause)
{
BOOST_CHECK_EQUAL(formula("x*5 where x=1").evaluate().as_int(), 5);
BOOST_CHECK_EQUAL(formula("x*5 where x=2").evaluate().as_int(), 10);
BOOST_CHECK_EQUAL(formula("x*(a*b where a=2,b=1) where x=5").evaluate().as_int(), 10);
BOOST_CHECK_EQUAL(formula("char.strength * ability where ability=3").evaluate(p).as_int(), 45);
}
BOOST_AUTO_TEST_CASE(test_formula_strings)
{
BOOST_CHECK_EQUAL(formula("'abcd' = 'abcd'").evaluate().as_bool(), true);
BOOST_CHECK_EQUAL(formula("'abcd' = 'acd'").evaluate().as_bool(), false);
BOOST_CHECK_EQUAL(formula("'ab' .. 'cd'").evaluate().as_string(), "abcd");
BOOST_CHECK_EQUAL(formula("'strength, agility: [strength], [agility]'").evaluate(c).as_string(),
"strength, agility: 15, 12");
}
BOOST_AUTO_TEST_CASE(test_formula_dice) {
const int dice_roll = formula("3d6").evaluate().as_int();
assert(dice_roll >= 3 && dice_roll <= 18);
}
BOOST_AUTO_TEST_CASE(test_formula_containers) {
variant myarray = formula("[1,2,3]").evaluate();
BOOST_CHECK_EQUAL(myarray.num_elements(), 3);
BOOST_CHECK_EQUAL(myarray[0].as_int(), 1);
BOOST_CHECK_EQUAL(myarray[1].as_int(), 2);
BOOST_CHECK_EQUAL(myarray[2].as_int(), 3);
variant mydict = formula("['foo' -> 5, 'bar' ->7]").evaluate();
BOOST_CHECK_EQUAL(mydict.num_elements(), 2);
BOOST_CHECK_EQUAL(mydict[variant("foo")].as_int(), 5);
BOOST_CHECK_EQUAL(mydict[variant("bar")].as_int(), 7);
variant myrange = formula("-2~2").evaluate();
BOOST_CHECK_EQUAL(myrange.num_elements(), 5);
BOOST_CHECK_EQUAL(myrange[0].as_int(), -2);
BOOST_CHECK_EQUAL(myrange[1].as_int(), -1);
BOOST_CHECK_EQUAL(myrange[2].as_int(), 0);
BOOST_CHECK_EQUAL(myrange[3].as_int(), 1);
BOOST_CHECK_EQUAL(myrange[4].as_int(), 2);
variant myslice = formula("(10~20)[[1,3,7,9]]").evaluate();
BOOST_CHECK_EQUAL(myslice.num_elements(), 4);
BOOST_CHECK_EQUAL(myslice[0].as_int(), 11);
BOOST_CHECK_EQUAL(myslice[1].as_int(), 13);
BOOST_CHECK_EQUAL(myslice[2].as_int(), 17);
BOOST_CHECK_EQUAL(myslice[3].as_int(), 19);
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -21,6 +21,8 @@
#include <cmath>
using namespace game_logic;
BOOST_AUTO_TEST_SUITE(formula_function)
BOOST_AUTO_TEST_CASE(test_formula_function_substring)
@ -141,6 +143,19 @@ BOOST_AUTO_TEST_CASE(test_formula_function_concatenate)
, "1.000, 1.000, 1.000, 1.200, 1.230, 1.234");
}
BOOST_AUTO_TEST_CASE(test_formula_function_math)
{
BOOST_CHECK_EQUAL(formula("abs(5)").evaluate().as_int(), 5);
BOOST_CHECK_EQUAL(formula("abs(-5)").evaluate().as_int(), 5);
BOOST_CHECK_EQUAL(formula("min(3,5)").evaluate().as_int(), 3);
BOOST_CHECK_EQUAL(formula("min(5,2)").evaluate().as_int(), 2);
BOOST_CHECK_EQUAL(formula("max(3,5)").evaluate().as_int(), 5);
BOOST_CHECK_EQUAL(formula("max(5,2)").evaluate().as_int(), 5);
BOOST_CHECK_EQUAL(formula("max(4,5,[2,18,7])").evaluate().as_int(), 18);
}
BOOST_AUTO_TEST_CASE(test_formula_function_sin_cos)
{
const double pi = 4. * atan(1.);