UFO: Alien Invasion
Loading...
Searching...
No Matches
test_scripts.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24*/
25
26#include "test_shared.h"
27#include "../client/client.h"
28#include "../client/cl_lua.h"
29#include "../client/renderer/r_state.h" /* r_state */
33
34class ScriptTest: public ::testing::Test {
35protected:
36 static void SetUpTestCase() {
37 TEST_Init();
38
39 cl_genericPool = Mem_CreatePool("Client: Generic");
40 vid_imagePool = Mem_CreatePool("Vid: Image system");
41
42 r_state.active_texunit = &r_state.texunits[0];
43 R_FontInit();
44 CL_InitLua();
45 UI_Init();
46
47 OBJZERO(cls);
48 Com_ParseScripts(false);
49 }
50
51 static void TearDownTestCase() {
53 }
54};
55
56static bool TEST_CheckImage (const char* path)
57{
58 const char* extensions[] = {"png", "tga", "jpg", nullptr};
59 int i = 0;
60
61 if (Q_strnull(path))
62 return true;
63
64 while (extensions[i]) {
65 if (FS_CheckFile("pics/%s.%s", path, extensions[i]) != -1)
66 return true;
67 i++;
68 }
69
70 return false;
71}
72
73static bool TEST_CheckModel (const char* path)
74{
75 const char* extensions[] = {"md2", "md3", "obj", nullptr};
76 int i = 0;
77 if (Q_strnull(path))
78 return true;
79
80 while (extensions[i]) {
81 if (FS_CheckFile("models/%s.%s", path, extensions[i]) != -1)
82 return true;
83 i++;
84 }
85
86 return false;
87}
88
89static bool TEST_CheckSound (const char* path)
90{
91 const char* extensions[] = {"wav", "ogg", nullptr};
92 int i = 0;
93
94 if (Q_strnull(path))
95 return true;
96
97 while (extensions[i]) {
98 if (FS_CheckFile("sound/%s.%s", path, extensions[i]) != -1)
99 return true;
100 i++;
101 }
102
103 return false;
104}
105
106static bool TEST_CheckParticle (const char* particleID)
107{
108 if (Q_strnull(particleID))
109 return true;
110
111 /* find the particle definition */
112 return CL_ParticleGet(particleID) != nullptr;
113}
114
116{
117 for (int i = 0; i < csi.numTeamDefs; i++) {
118 const teamDef_t* teamDef = &csi.teamDef[i];
119
120 ASSERT_TRUE(teamDef->numTemplates > 0) << teamDef->id << " has no character templates assigned";
121
122 for (int k = 0; k < SND_MAX; k++) {
123 for (int l = 0; l < NAME_LAST; l++) {
124 LIST_Foreach(teamDef->sounds[k][l], char, soundFile) {
125 ASSERT_TRUE(TEST_CheckSound(soundFile)) << "sound " << soundFile << " does not exist (team " << teamDef->id << ")";
126 }
127 }
128 }
129 }
130}
131
132TEST_F(ScriptTest, TeamDefsModelScriptData)
133{
134 linkedList_t* armourPaths = nullptr;
135
136 for (int i = 0; i < csi.numTeamDefs; i++) {
137 const teamDef_t* teamDef = &csi.teamDef[i];
138 if (!teamDef->armour)
139 continue;
140
141 for (int j = 0; j < csi.numODs; j++) {
142 const objDef_t* od = INVSH_GetItemByIDX(j);
143 if (!od->isArmour())
144 continue;
145
146 /* not for this team */
147 if (!CHRSH_IsArmourUseableForTeam(od, teamDef))
148 continue;
149
150 if (!LIST_ContainsString(armourPaths, od->armourPath))
151 LIST_AddString(&armourPaths, od->armourPath);
152 }
153
154 ASSERT_TRUE(!LIST_IsEmpty(armourPaths)) << "no armour definitions found for team " << teamDef->id << " - but armour is set to true";
155
156 LIST_Foreach(armourPaths, char const, armourPath) {
157 for (int l = NAME_NEUTRAL; l < NAME_LAST; l++) {
158 /* no models for this gender */
159 if (!teamDef->numModels[l])
160 continue;
161
162 ASSERT_TRUE(nullptr != teamDef->models[l]);
163
164 for (linkedList_t const* list = teamDef->models[l]; list; list = list->next) {
165 teamDef_t::model_t const& m = *static_cast<teamDef_t::model_t const*>(list->data);
166
167 ASSERT_TRUE(TEST_CheckModel(va("%s/%s", m.path, m.body))) << m.body << " does not exist in models/" << m.path << " (teamDef: " << teamDef->id << ")";
168 ASSERT_TRUE(TEST_CheckModel(va("%s%s/%s", m.path, armourPath, m.body))) << m.body << " does not exist in models/" << m.path << armourPath << " (teamDef: " << teamDef->id << ")";
169
170 ASSERT_TRUE(TEST_CheckModel(va("%s/%s", m.path, m.head))) << m.head << " does not exist in models/" << m.path << " (teamDef: " << teamDef->id << ")";
171 ASSERT_TRUE(TEST_CheckModel(va("%s%s/%s", m.path, armourPath, m.head))) << m.head << " does not exist in models/" << m.path << armourPath << " (teamDef: " << teamDef->id << ")";
172 }
173 }
174 }
175
176 LIST_Delete(&armourPaths);
177 }
178}
179
181{
182 for (int j = 0; j < csi.numODs; j++) {
183 const objDef_t* od = INVSH_GetItemByIDX(j);
184 if (od->isVirtual || od->isDummy)
185 continue;
186
187 ASSERT_TRUE(TEST_CheckSound(od->reloadSound)) << "sound " << od->reloadSound << " does not exist (item " << od->id << ")";
188 ASSERT_TRUE(TEST_CheckModel(od->model)) << "model " << od->model << " does not exist (item " << od->id << ")";
189 ASSERT_TRUE(TEST_CheckImage(od->image)) << "image " << od->image << " does not exist (item " << od->id << ")";
190
191 for (int i = 0; i < od->numWeapons; i++) {
192 for (int k = 0; k < od->numFiredefs[i]; k++) {
193 const fireDef_t* fd = &od->fd[i][k];
194 ASSERT_TRUE(TEST_CheckSound(fd->bounceSound)) << "sound " << fd->bounceSound << " does not exist (firedef " << fd->name << " for item " << od->id << ")";
195 ASSERT_TRUE(TEST_CheckSound(fd->fireSound)) << "sound " << fd->fireSound << " does not exist (firedef " << fd->name << " for item " << od->id << ")";
196 ASSERT_TRUE(TEST_CheckSound(fd->impactSound)) << "sound " << fd->impactSound << " does not exist (firedef " << fd->name << " for item " << od->id << ")";
197 ASSERT_TRUE(TEST_CheckSound(fd->hitBodySound)) << "sound " << fd->hitBodySound << " does not exist (firedef " << fd->name << " for item " << od->id << ")";
198 ASSERT_TRUE(TEST_CheckParticle(fd->hitBody)) << "particle " << fd->hitBody << " does not exist (firedef " << fd->name << " for item " << od->id << ")";
199 ASSERT_TRUE(TEST_CheckParticle(fd->impact)) << "particle " << fd->impact << " does not exist (firedef " << fd->name << " for item " << od->id << ")";
200 ASSERT_TRUE(TEST_CheckParticle(fd->projectile)) << "particle " << fd->projectile << " does not exist (firedef " << fd->name << " for item " << od->id << ")";
201 }
202 }
203 }
204}
205
207{
208 NAT_Foreach(nation) {
209 ASSERT_TRUE(TEST_CheckImage(va("nations/%s", nation->id))) << "nation " << nation->id << " has no image";
210 ASSERT_TRUE(nullptr != Com_GetTeamDefinitionByID(nation->id));
211 }
212}
213
215{
216 AIR_Foreach(aircraft) {
217 ASSERT_TRUE(TEST_CheckModel(aircraft->model)) << aircraft->model << " does not exist (aircraft: " << aircraft->id << ")";
218 ASSERT_TRUE(TEST_CheckImage(aircraft->image)) << aircraft->image << " does not exist (aircraft: " << aircraft->id << ")";
219 }
220}
221
223{
224 const mapDef_t* md;
225
226 int i = 0;
227 MapDef_Foreach(md) {
228 if (md->civTeam != nullptr) {
229 ASSERT_TRUE(nullptr != Com_GetTeamDefinitionByID(md->civTeam));
230 }
231
232 ASSERT_FALSE(md->maxAliens <= 0);
233 ASSERT_TRUE(nullptr != md->mapTheme);
234 ASSERT_TRUE(nullptr != md->description);
235 i++;
236 }
237
238 ASSERT_TRUE(nullptr == md);
239 ASSERT_EQ(i, csi.numMDs) << "only looped over " << i << " mapdefs, but expected " << csi.numMDs;
240
241 i = csi.numMDs;
242
244 i--;
245 ASSERT_TRUE(nullptr != md);
246 }
247
248 ASSERT_TRUE(nullptr == md);
249 ASSERT_NE(i, csi.numMDs);
250
252 i--;
253 ASSERT_TRUE(nullptr != md);
254 ASSERT_STRNE(md->id, "training_a");
255 ASSERT_STRNE(md->id, "training_b");
256 }
257
258 ASSERT_TRUE(nullptr == md);
259 ASSERT_EQ(i, 0);
260}
bool CHRSH_IsArmourUseableForTeam(const objDef_t *od, const teamDef_t *teamDef)
@ NAME_LAST
Definition chr_shared.h:237
@ NAME_NEUTRAL
Definition chr_shared.h:233
@ SND_MAX
Definition chr_shared.h:222
void CL_InitLua(void)
Initializes the ui-lua interfacing environment.
Definition cl_lua.cpp:130
memPool_t * vid_imagePool
Definition cl_main.cpp:88
client_static_t cls
Definition cl_main.cpp:83
memPool_t * cl_genericPool
Definition cl_main.cpp:86
ptlDef_t * CL_ParticleGet(const char *name)
void R_FontInit(void)
Definition r_font.cpp:716
#define MapDef_ForeachSingleplayerCampaign(var)
Definition cl_shared.h:84
static void TearDownTestCase()
static void SetUpTestCase()
Primary header for client.
csi_t csi
Definition common.cpp:39
#define AIR_Foreach(var)
iterates trough all aircraft
Header file for single player campaign control.
#define NAT_Foreach(var)
iterates trough nations
Definition cp_nation.h:80
int FS_CheckFile(const char *fmt,...)
Just returns the filelength and -1 if the file wasn't found.
Definition files.cpp:298
const objDef_t * INVSH_GetItemByIDX(int index)
Returns the item that belongs to the given index or nullptr if the index is invalid.
void LIST_AddString(linkedList_t **listDest, const char *data)
Adds an string to a new or to an already existing linked list. The string is copied here.
Definition list.cpp:139
void LIST_Delete(linkedList_t **list)
Definition list.cpp:195
bool LIST_IsEmpty(const linkedList_t *list)
Checks whether the given list is empty.
Definition list.cpp:335
const linkedList_t * LIST_ContainsString(const linkedList_t *list, const char *string)
Searches for the first occurrence of a given string.
Definition list.cpp:73
#define LIST_Foreach(list, type, var)
Iterates over a linked list, it's safe to delete the returned entry from the list while looping over ...
Definition list.h:41
static struct mdfour * m
Definition md4.cpp:35
#define Mem_CreatePool(name)
Definition mem.h:32
#define MapDef_ForeachCondition(var, condition)
Definition q_shared.h:501
#define MapDef_Foreach(var)
Definition q_shared.h:505
QGL_EXTERN GLint i
Definition r_gl.h:113
rstate_t r_state
Definition r_main.cpp:48
const teamDef_t * Com_GetTeamDefinitionByID(const char *team)
Returns the teamDef pointer for the searched team id - or nullptr if not found in the teamDef array.
Definition scripts.cpp:2345
void Com_ParseScripts(bool onlyServer)
Definition scripts.cpp:3619
bool Q_strnull(const char *string)
Definition shared.h:138
#define OBJZERO(obj)
Definition shared.h:178
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition shared.cpp:410
this is a fire definition for our weapons/ammo
Definition inv_shared.h:110
const char * fireSound
Definition inv_shared.h:117
const char * name
Definition inv_shared.h:111
const char * projectile
Definition inv_shared.h:112
const char * hitBodySound
Definition inv_shared.h:116
const char * bounceSound
Definition inv_shared.h:118
const char * impact
Definition inv_shared.h:113
const char * impactSound
Definition inv_shared.h:114
const char * hitBody
Definition inv_shared.h:115
linkedList_t * next
Definition list.h:32
char * mapTheme
Definition q_shared.h:464
char * id
Definition q_shared.h:463
char * civTeam
Definition q_shared.h:471
int maxAliens
Definition q_shared.h:483
bool campaign
Definition q_shared.h:480
char * description
Definition q_shared.h:466
bool singleplayer
Definition q_shared.h:481
Defines all attributes of objects used in the inventory.
Definition inv_shared.h:264
const char * armourPath
Definition inv_shared.h:272
bool isVirtual
Definition inv_shared.h:284
fireDef_t fd[MAX_WEAPONS_PER_OBJDEF][MAX_FIREDEFS_PER_WEAPON]
Definition inv_shared.h:314
bool isDummy
Definition inv_shared.h:290
fireDefIndex_t numFiredefs[MAX_WEAPONS_PER_OBJDEF]
Definition inv_shared.h:315
const char * image
Definition inv_shared.h:270
const char * model
Definition inv_shared.h:269
const char * id
Definition inv_shared.h:268
bool isArmour() const
Definition inv_shared.h:346
int numWeapons
Definition inv_shared.h:317
const char * reloadSound
Definition inv_shared.h:297
int numModels[NAME_LAST]
Definition chr_shared.h:326
linkedList_t * sounds[SND_MAX][NAME_LAST]
Definition chr_shared.h:328
char id[MAX_VAR]
Definition chr_shared.h:309
linkedList_t * models[NAME_LAST]
Definition chr_shared.h:325
bool armour
Definition chr_shared.h:334
int numTemplates
Definition chr_shared.h:348
static bool TEST_CheckParticle(const char *particleID)
static bool TEST_CheckSound(const char *path)
static bool TEST_CheckImage(const char *path)
TEST_F(ScriptTest, TeamDefs)
static bool TEST_CheckModel(const char *path)
void TEST_Shutdown(void)
void TEST_Init(void)
void UI_Init(void)
Definition ui_main.cpp:278