Skip to content

Commit

Permalink
Transfer original formula unit tests to Boost framework
Browse files Browse the repository at this point in the history
In the process, I have corrected a few tests and added a few extras
  • Loading branch information
CelticMinstrel committed Mar 18, 2016
1 parent e78b5d7 commit f6be40b
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 93 deletions.
4 changes: 4 additions & 0 deletions projectfiles/Xcode/Wesnoth.xcodeproj/project.pbxproj
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -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>"; };
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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;
};
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/SConscript
Expand Up @@ -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
Expand Down
93 changes: 0 additions & 93 deletions src/formula.cpp
Expand Up @@ -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
175 changes: 175 additions & 0 deletions src/tests/test_formula_core.cpp
@@ -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()
15 changes: 15 additions & 0 deletions src/tests/test_formula_function.cpp
Expand Up @@ -21,6 +21,8 @@

#include <cmath>

using namespace game_logic;

BOOST_AUTO_TEST_SUITE(formula_function)

BOOST_AUTO_TEST_CASE(test_formula_function_substring)
Expand Down Expand Up @@ -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.);
Expand Down

0 comments on commit f6be40b

Please sign in to comment.