123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509 |
- /*
- * =====================================================================================
- *
- * Filename: catch-entityconverter.cpp
- *
- * Description: Unit tests for EntityConverter class
- *
- * Version: 1.0
- * Created: 07/14/2017 20:36:31 PM
- * Revision: none
- * Compiler: gcc
- *
- * Author: surkeh@protonmail.com
- *
- * =====================================================================================
- */
- #include <cmath>
- #include <queue>
- #include <vector>
- #include <sstream>
- #include "EntityConverter.hpp"
- #define ENTITY_FILENAME "r2xonotic.rem"
- #define DELTA 0.00001
- TEST_CASE ("r2x: Unsupported entity types cause return of empty vector", "[EntityConverter]") {
-
- // Instantiate object
- EntityConverter ec (ENTITY_FILENAME);
-
- // Mock up entity
- std::vector<std::string> entity;
- entity.push_back (" type NotAType");
- // Mock up entity queue
- std::queue<std::vector<std::string>> q;
- q.push (entity);
- // Match related entities (none)
- ec.extractMapInfo (q);
-
- // Convert a single entity
- std::vector<std::string> converted = ec.convert (entity);
- REQUIRE (converted.size() == 0);
- }
- TEST_CASE ("r2x: a single Pickup entity can be converted", "[EntityConverter]") {
-
- // Instantiate object
- EntityConverter ec (ENTITY_FILENAME);
-
- // Mock up entity
- std::vector<std::string> entity;
- entity.push_back (" type Pickup");
- entity.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
- entity.push_back (" Vector3 angles 180.00000 0.00000 0.00000");
- entity.push_back (" UInt8 pickupType 2");
- // Mock up entity queue
- std::queue<std::vector<std::string>> q;
- q.push (entity);
- // Match related entities (none)
- ec.extractMapInfo (q);
-
- // Convert a single entity
- std::vector<std::string> converted = ec.convert (entity);
- REQUIRE (converted[0] == "\"classname\" \"weapon_grenadelauncher\"\n");
- // The z (vertical) is offset by +2
- std::istringstream iss (converted[1]);
- std::string attribute;
- std::string coords[2];
- float offsetCoord;
- iss >> attribute >> coords[0] >> coords[1] >> offsetCoord;
- REQUIRE (attribute == "\"origin\"");
- REQUIRE (coords[0] == "\"-216.00000");
- REQUIRE (coords[1] == "-1488.000488");
- REQUIRE (fabs(-130.00000 - offsetCoord) <= DELTA);
- }
- TEST_CASE ("r2x: a single PlayerSpawn (race) entity can be converted", "[EntityConverter]") {
-
- // Instantiate object
- EntityConverter ec (ENTITY_FILENAME);
-
- // Mock up WorldSpawn entity
- // (needed for mode info)
- std::vector<std::string> worldspawn;
- worldspawn.push_back (" type WorldSpawn");
- worldspawn.push_back (" Bool8 modeCTF 0");
- worldspawn.push_back (" Bool8 modeFFA 0");
- worldspawn.push_back (" Bool8 modeTDM 0");
- worldspawn.push_back (" Bool8 mode1v1 0");
- // Mock up entity
- std::vector<std::string> entity;
- entity.push_back (" type PlayerSpawn");
- entity.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
- entity.push_back (" Vector3 angles 180.00000 0.00000 0.00000");
- entity.push_back (" Bool8 teamA 0");
- entity.push_back (" Bool8 teamB 0");
- entity.push_back (" Bool8 modeCTF 0");
- entity.push_back (" Bool8 modeFFA 0");
- entity.push_back (" Bool8 modeTDM 0");
- entity.push_back (" Bool8 mode1v1 0");
- // Mock up entity queue
- std::queue<std::vector<std::string>> q;
- q.push (worldspawn);
- q.push (entity);
- // Match related entities (none)
- ec.extractMapInfo (q);
-
- // Convert a single entity (worldspawn conversion returns empty vector
- // BUT sets the supported game modes for entities in that worldspawn
- std::vector<std::string> unused = ec.convert(worldspawn);
- std::vector<std::string> converted = ec.convert(entity);
- REQUIRE (converted[0] == "\"classname\" \"info_player_start\"\n");
-
- // The z (vertical) is offset by +32
- std::istringstream iss (converted[1]);
- std::string attribute;
- std::string coords[2];
- float offsetCoord;
- iss >> attribute >> coords[0] >> coords[1] >> offsetCoord;
- REQUIRE (attribute == "\"origin\"");
- REQUIRE (coords[0] == "\"-216.00000");
- REQUIRE (coords[1] == "-1488.000488");
- REQUIRE (fabs(-100.00000 - offsetCoord) <= DELTA);
- SECTION( "Converted angles are valid (Different coordinate system handedness)") {
- std::istringstream angleLineStream(converted[2]);
- std::string angleAttribute;
- std::string a;
- float angle;
- angleLineStream >> attribute >> a;
- a.erase(a.begin()); //removing preceding quote is necessary
- std::stringstream angleStream(a);
- angleStream >> angle;
- REQUIRE (attribute == "\"angle\"");
- REQUIRE (fabs (-90.0 - angle) <= DELTA);
- }
- SECTION( "Encountering a new worldspawn reenables all modes") {
- std::vector<std::string> basicWorldspawn;
- basicWorldspawn.push_back (" type WorldSpawn");
- std::vector<std::string> e;
- e.push_back (" type PlayerSpawn");
- e.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
- e.push_back (" Vector3 angles 180.00000 0.00000 0.00000");
- std::vector<std::string> u = ec.convert(basicWorldspawn);
- std::vector<std::string> c = ec.convert(e);
- REQUIRE (c[0] == "\"classname\" \"info_player_deathmatch\"\n");
- }
- }
- TEST_CASE ("r2x: a single PlayerSpawn (teamA) entity can be converted", "[EntityConverter]") {
-
- // Instantiate object
- EntityConverter ec (ENTITY_FILENAME);
-
- // Mock up entity
- std::vector<std::string> entity;
- entity.push_back (" type PlayerSpawn");
- entity.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
- entity.push_back (" Vector3 angles 180.00000 0.00000 0.00000");
- entity.push_back (" Bool8 teamB 0");
- entity.push_back (" Bool8 modeRace 0");
- // Mock up entity queue
- std::queue<std::vector<std::string>> q;
- q.push (entity);
- // Match related entities (none)
- ec.extractMapInfo (q);
-
- // Convert a single entity
- std::vector<std::string> converted = ec.convert(entity);
- REQUIRE (converted[0] == "\"classname\" \"info_player_team1\"\n");
-
- // The z (vertical) is offset by +32
- std::istringstream iss (converted[1]);
- std::string attribute;
- std::string coords[2];
- float offsetCoord;
- iss >> attribute >> coords[0] >> coords[1] >> offsetCoord;
- REQUIRE (attribute == "\"origin\"");
- REQUIRE (coords[0] == "\"-216.00000");
- REQUIRE (coords[1] == "-1488.000488");
- REQUIRE (fabs(-100.00000 - offsetCoord) <= DELTA);
- }
- TEST_CASE ("r2x: a single PlayerSpawn (non-team) entity can be converted", "[EntityConverter]") {
-
- // Instantiate object
- EntityConverter ec (ENTITY_FILENAME);
-
- // Mock up entity
- std::vector<std::string> entity;
- entity.push_back (" type PlayerSpawn");
- entity.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
- entity.push_back (" Vector3 angles 180.00000 0.00000 0.00000");
- // Mock up entity queue
- std::queue<std::vector<std::string>> q;
- q.push (entity);
- // Match related entities (none)
- ec.extractMapInfo (q);
-
- // Convert a single entity
- std::vector<std::string> converted = ec.convert(entity);
- REQUIRE (converted[0] == "\"classname\" \"info_player_deathmatch\"\n");
-
- // The z (vertical) is offset by +32
- std::istringstream iss (converted[1]);
- std::string attribute;
- std::string coords[2];
- float offsetCoord;
- iss >> attribute >> coords[0] >> coords[1] >> offsetCoord;
- REQUIRE (attribute == "\"origin\"");
- REQUIRE (coords[0] == "\"-216.00000");
- REQUIRE (coords[1] == "-1488.000488");
- REQUIRE (fabs(-100.00000 - offsetCoord) <= DELTA);
- }
- TEST_CASE ("r2x: a single RaceStart entity can be converted", "[EntityConverter]") {
-
- // Instantiate object
- EntityConverter ec (ENTITY_FILENAME);
-
- // Mock up entity
- std::vector<std::string> entity;
- entity.push_back (" type RaceStart");
- // Mock up entity queue
- std::queue<std::vector<std::string>> q;
- q.push (entity);
- // Match related entities (none)
- ec.extractMapInfo (q);
-
- // Convert a single entity
- std::vector<std::string> converted = ec.convert(entity);
- REQUIRE (converted[0] == "\"classname\" \"trigger_race_checkpoint\"\n");
- REQUIRE (converted[1] == "\"targetname\" \"cp1\"\n");
- REQUIRE (converted[2] == "\"cnt\" \"0\"\n");
- }
- TEST_CASE ("r2x: a single RaceFinish entity can be converted", "[EntityConverter]") {
-
- // Instantiate object
- EntityConverter ec (ENTITY_FILENAME);
-
- // Mock up entity
- std::vector<std::string> entity;
- entity.push_back (" type RaceFinish");
- // Mock up entity queue
- std::queue<std::vector<std::string>> q;
- q.push (entity);
- // Match related entities (none)
- ec.extractMapInfo (q);
-
- // Convert a single entity
- std::vector<std::string> converted = ec.convert(entity);
- REQUIRE (converted[0] == "\"classname\" \"trigger_race_checkpoint\"\n");
- REQUIRE (converted[1] == "\"targetname\" \"finish\"\n");
- REQUIRE (converted[2] == "\"cnt\" \"1\"\n");
- }
- TEST_CASE ("r2x: a single Teleporter and related Target can be converted", "[EntityConverter]") {
-
- // Instantiate object
- EntityConverter ec (ENTITY_FILENAME);
-
- // Mock up Teleporter entity
- std::vector<std::string> entity;
- entity.push_back (" type Teleporter");
- entity.push_back (" String32 target tp1");
- // Mock up Target entity
- std::vector<std::string> entity2;
- entity2.push_back (" type Target");
- entity2.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
- entity2.push_back (" String32 name tp1");
- // Mock up entity queue
- std::queue<std::vector<std::string>> q;
- q.push (entity);
- q.push (entity2);
- // Match related entities (one pair)
- ec.extractMapInfo (q);
-
- // Convert two entities
- std::vector<std::string> converted = ec.convert(entity);
- REQUIRE (converted[0] == "\"classname\" \"trigger_teleport\"\n");
- REQUIRE (converted[1] == "\"target\" \"tp1\"\n");
- std::vector<std::string> converted2 = ec.convert(entity2);
- REQUIRE (converted2[0] == "\"classname\" \"misc_teleporter_dest\"\n");
- REQUIRE (converted2[2] == "\"targetname\" \"tp1\"\n");
- //
- // The z (vertical) is offset by +32
- std::istringstream iss (converted2[1]);
- std::string attribute;
- std::string coords[2];
- float offsetCoord;
- iss >> attribute >> coords[0] >> coords[1] >> offsetCoord;
- // next REQUIRE fails without busy wait
- for( int i = 0; i < 10000000; i++)
- int x = i;
- REQUIRE (attribute == "\"origin\"");
- REQUIRE (coords[0] == "\"-216.00000");
- REQUIRE (coords[1] == "-1488.000488");
- REQUIRE (fabs(-100.00000 - offsetCoord) <= DELTA);
- SECTION( "When angle unspecified, defaults to 0.0 (converted to 90.0)") {
- std::istringstream angleStream(converted2[3]);
- std::string a;
- float angle;
- angleStream >> attribute >> a;
- a.erase(a.begin()); //removing preceding quote is necessary
- std::stringstream out(a);
- out >> angle;
- REQUIRE (fabs(90.0 - angle) <= DELTA);
- }
- }
- TEST_CASE ("r2x: a single JumpPad and related Target can be converted", "[EntityConverter]") {
-
- // Instantiate object
- EntityConverter ec (ENTITY_FILENAME);
-
- // Mock up JumpPad entity
- std::vector<std::string> entity;
- entity.push_back (" type JumpPad");
- entity.push_back (" String32 target jp1");
- // Mock up Target entity
- std::vector<std::string> entity2;
- entity2.push_back (" type Target");
- entity2.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
- entity2.push_back (" String32 name jp1");
- // Mock up entity queue
- std::queue<std::vector<std::string>> q;
- q.push (entity);
- q.push (entity2);
- // Match related entities (one pair)
- ec.extractMapInfo (q);
-
- // Convert two entities
- std::vector<std::string> converted = ec.convert(entity);
- REQUIRE (converted[0] == "\"classname\" \"trigger_push\"\n");
- REQUIRE (converted[1] == "\"target\" \"jp1\"\n");
- std::vector<std::string> converted2 = ec.convert(entity2);
- REQUIRE (converted2[0] == "\"classname\" \"target_position\"\n");
- REQUIRE (converted2[1] == "\"origin\" \"-216.00000 -1488.000488 -132.00000\"\n");
- REQUIRE (converted2[2] == "\"targetname\" \"jp1\"\n");
- }
- TEST_CASE ("r2x: a single PointLight entity can be converted", "[EntityConverter]") {
-
- // Instantiate object
- EntityConverter ec (ENTITY_FILENAME);
-
- // Mock up entity
- std::vector<std::string> entity;
- entity.push_back (" type PointLight");
- entity.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
- entity.push_back (" ColourXRGB32 color ffffc400");
- entity.push_back (" Float intensity 1.500000");
- entity.push_back (" Float nearAttenuation 32.000000");
- entity.push_back (" Float farAttenuation 160.000000");
- // Mock up entity queue
- std::queue<std::vector<std::string>> q;
- q.push (entity);
- // Match related entities (none)
- ec.extractMapInfo (q);
-
- // Convert a single entity
- std::vector<std::string> converted = ec.convert(entity);
- REQUIRE (converted[0] == "\"classname\" \"light\"\n");
- REQUIRE (converted[1] == "\"origin\" \"-216.00000 -1488.000488 -132.00000\"\n");
- REQUIRE (converted[2] == "\"light\" \"75\"\n");
- INFO (converted[3]);
- std::istringstream iss (converted[3]);
- std::string attribute;
- std::string r;
- float red;
- float green;
- float blue;
- iss >> attribute >> r >> green >> blue;
- r.erase(r.begin()); //removing preceding quote is necessary
- std::stringstream redStream(r);
- redStream >> red;
- REQUIRE (attribute == "\"_color\"");
- REQUIRE (fabs (1.0 - red) <= DELTA);
- REQUIRE (fabs (0.768627 - green) <= DELTA);
- REQUIRE (fabs (0.0 - blue) <= DELTA);
- }
- TEST_CASE ("r2x: PointLight defaults to white light of typical intensity", "[EntityConverter]") {
-
- // Instantiate object
- EntityConverter ec (ENTITY_FILENAME);
-
- // Mock up entity
- std::vector<std::string> entity;
- entity.push_back (" type PointLight");
- entity.push_back (" Vector3 position -216.00000 -132.00000 -1488.000488");
- // Mock up entity queue
- std::queue<std::vector<std::string>> q;
- q.push (entity);
- // Match related entities (none)
- ec.extractMapInfo (q);
-
- // Convert a single entity
- std::vector<std::string> converted = ec.convert(entity);
- REQUIRE (converted[0] == "\"classname\" \"light\"\n");
- REQUIRE (converted[1] == "\"origin\" \"-216.00000 -1488.000488 -132.00000\"\n");
- REQUIRE (converted[2] == "\"light\" \"50\"\n");
- INFO (converted[3]);
- std::istringstream iss (converted[3]);
- std::string attribute;
- std::string r;
- float red;
- float green;
- float blue;
- iss >> attribute >> r >> green >> blue;
- r.erase (r.begin()); //removing preceding quote is necessary
- std::stringstream redStream (r);
- redStream >> red;
- REQUIRE (attribute == "\"_color\"");
- REQUIRE (fabs (0.0 - red) <= DELTA);
- REQUIRE (fabs (0.0 - green) <= DELTA);
- REQUIRE (fabs (0.0 - blue) <= DELTA);
- }
|