reflex2q3/test/catch-entityconverter.cpp

509 lines
14 KiB
C++
Raw Permalink Normal View History

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