mirror of
https://github.com/nzp-team/quakec.git
synced 2025-03-13 06:12:08 +00:00
SERVER/YML: Add Unit test infrastructure
This commit is contained in:
parent
62228b72d8
commit
4ac4c8934c
17 changed files with 1084 additions and 9 deletions
18
.github/workflows/unit-tests.yml
vendored
Normal file
18
.github/workflows/unit-tests.yml
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
name: QuakeC Unit Tests
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
Unit-Tests:
|
||||
name: Run Unit Tests
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ubuntu:24.10
|
||||
options: --shm-size=8192m
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Wait for GitHub to keep up..
|
||||
run: sleep 2s
|
||||
shell: bash
|
||||
- name: Run Unit Test Script
|
||||
run: |
|
||||
bash testing/run_unit_tests.sh
|
|
@ -77,4 +77,13 @@ ai/zombie_core.qc
|
|||
ai/crawler_core.qc
|
||||
ai/dog_core.qc
|
||||
utilities/map_compatibility.qc
|
||||
#ifdef QUAKEC_TEST
|
||||
tests/test_math.qc
|
||||
tests/test_perksacola.qc
|
||||
tests/test_weapons.qc
|
||||
tests/test_misc_model.qc
|
||||
tests/test_score.qc
|
||||
tests/test_ai.qc
|
||||
tests/test_module.qc
|
||||
#endif
|
||||
#endlist
|
||||
|
|
|
@ -423,7 +423,7 @@ void(entity who) makeCrawler;
|
|||
void() spawnAllZombEnts;
|
||||
void() set_z_health;
|
||||
float() spawn_a_zombieA;
|
||||
float gotdog;
|
||||
float map_has_hellhounds;
|
||||
float dogRound;
|
||||
float dogWave;
|
||||
float dog_round_count;
|
||||
|
|
|
@ -31,6 +31,8 @@ void() MBOX_Touch;
|
|||
#define MBOX_SPAWNFLAG_NOTHERE 1
|
||||
#define MBOX_SPAWNFLAG_NOLIGHT 2
|
||||
|
||||
float mystery_box_file_parsed;
|
||||
|
||||
//
|
||||
// MBOX_UpdateGlowFrame()
|
||||
// Updates the Glow model frame to match
|
||||
|
@ -925,6 +927,9 @@ void(float mbox_file) MBOX_ParseMB2File =
|
|||
//
|
||||
void() MBOX_LoadData =
|
||||
{
|
||||
if (mystery_box_file_parsed == true)
|
||||
return;
|
||||
|
||||
float mbox_file;
|
||||
string file_path;
|
||||
|
||||
|
@ -935,6 +940,7 @@ void() MBOX_LoadData =
|
|||
if (mbox_file != -1) {
|
||||
MBOX_ParseMB2File(mbox_file);
|
||||
fclose(mbox_file);
|
||||
mystery_box_file_parsed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -945,6 +951,7 @@ void() MBOX_LoadData =
|
|||
if (mbox_file != -1) {
|
||||
MBOX_ParseMB1File(mbox_file);
|
||||
fclose(mbox_file);
|
||||
mystery_box_file_parsed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -960,6 +967,7 @@ void() MBOX_LoadData =
|
|||
|
||||
// Close the file pointer just in case.
|
||||
fclose(mbox_file);
|
||||
mystery_box_file_parsed = true;
|
||||
}
|
||||
|
||||
void() mystery_box =
|
||||
|
|
|
@ -575,7 +575,7 @@ void() perk_double =
|
|||
// Deadshot Daiquiri
|
||||
void() perk_deadshot =
|
||||
{
|
||||
Perk_InitMachine("perk_deadshot", PERK_DEADSHOT_DEFAULT_MODEL, 2000, 2000,
|
||||
Perk_InitMachine("perk_deadshot", PERK_DEADSHOT_DEFAULT_MODEL, 1500, 1500,
|
||||
PERK_SPAWNFLAG_YELLOWLIGHT, 1000, 1000, true, true, 7, P_DEAD);
|
||||
};
|
||||
// naievil -- older maps compatability
|
||||
|
|
|
@ -135,7 +135,7 @@ void() StartFrame =
|
|||
entity hellhound = find(world, classname, "spawn_dog");
|
||||
|
||||
if (hellhound != world)
|
||||
gotdog = true;
|
||||
map_has_hellhounds = true;
|
||||
|
||||
Compat_Init();
|
||||
updateDogRound();
|
||||
|
|
|
@ -32,6 +32,12 @@ void() Spawns_Init;
|
|||
void() SUB_UseTargets;
|
||||
void(entity client) LastStand_UnlinkRevivee;
|
||||
|
||||
#ifdef QUAKEC_TEST
|
||||
|
||||
void() Test_RunAllTests;
|
||||
|
||||
#endif // QUAKEC_TEST
|
||||
|
||||
#define PLAYER_START_HEALTH 100
|
||||
|
||||
#define PLAYER_CROUCH_DIFFERENCE_HL 25
|
||||
|
@ -275,6 +281,9 @@ float(float dir) checkMovement =
|
|||
//
|
||||
void(entity who, float value, float impacted_by_2x_points) Player_ChangeScore =
|
||||
{
|
||||
if (who.classname != "player")
|
||||
return;
|
||||
|
||||
// We shouldn't ever allow a player in Last Stand to have
|
||||
// their score modified.
|
||||
if (who.downed)
|
||||
|
@ -815,6 +824,13 @@ void() PlayerPostThink =
|
|||
|
||||
player_trace_time = time + 0.05;
|
||||
}
|
||||
|
||||
#ifdef QUAKEC_TEST
|
||||
|
||||
if (time_before_gamestart != 0)
|
||||
Test_RunAllTests();
|
||||
|
||||
#endif // QUAKEC_TEST
|
||||
};
|
||||
|
||||
void() ClientKill = {};
|
||||
|
|
|
@ -138,7 +138,7 @@ void() EndRound =
|
|||
|
||||
rounds_change = 4;
|
||||
SetUpdate(self, UT_ROUNDS_CHANGE, rounds_change, 0, 0);
|
||||
if (gotdog && rounds == dogRound) {
|
||||
if (map_has_hellhounds && rounds == dogRound) {
|
||||
Rounds_PlayTransition("sounds/rounds/droundend.wav");
|
||||
dogWave = false;
|
||||
} else {
|
||||
|
@ -190,7 +190,7 @@ void() NewRound =
|
|||
}
|
||||
if (rounds != 0)
|
||||
{
|
||||
if (gotdog && rounds == (dogRound - 1)) {
|
||||
if (map_has_hellhounds && rounds == (dogRound - 1)) {
|
||||
Rounds_PlayTransition("sounds/rounds/droundstart.wav");
|
||||
dogWave = true;
|
||||
dog_round_count++;
|
||||
|
@ -203,7 +203,7 @@ void() NewRound =
|
|||
}
|
||||
|
||||
// if we just had a dog round, set the next
|
||||
if (gotdog && rounds == dogRound) {
|
||||
if (map_has_hellhounds && rounds == dogRound) {
|
||||
updateDogRound();
|
||||
}
|
||||
|
||||
|
@ -252,7 +252,7 @@ void() NewRound =
|
|||
spawn_delay = 0;
|
||||
totalpowerups = 0;
|
||||
|
||||
if (rounds == dogRound && gotdog) {
|
||||
if (rounds == dogRound && map_has_hellhounds) {
|
||||
roundtype = 2;
|
||||
localcmd("fog 200 525 54 55 60\n");
|
||||
} else {
|
||||
|
|
48
source/server/tests/test_ai.qc
Normal file
48
source/server/tests/test_ai.qc
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
server/tests/test_ai.qc
|
||||
|
||||
Unit tests for various AI behaviors
|
||||
|
||||
Copyright (C) 2021-2025 NZ:P Team
|
||||
|
||||
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; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
float(float condition, string message) Test_Assert;
|
||||
void(string message) Test_Skip;
|
||||
|
||||
//
|
||||
// Test_AI_HellhoundsDetected()
|
||||
// Validates that if a hellhound spawner is in the
|
||||
// world that we have detected we can have Hellhound
|
||||
// rounds.
|
||||
// (https://github.com/nzp-team/nzportable/issues/623)
|
||||
//
|
||||
void() Test_AI_HellhoundsDetected =
|
||||
{
|
||||
entity hound = find(world, classname, "spawn_dog");
|
||||
|
||||
if (hound != world) {
|
||||
Test_Assert((map_has_hellhounds == true), "Found Hellhound entities but map_has_hellhounds is false!");
|
||||
Test_Assert((dogRound >= 0), "Found Hellhound entities but dogRound is zero!");
|
||||
} else {
|
||||
Test_Assert((map_has_hellhounds == false), "No Hellhound entities found but map_has_hellhounds is true!");
|
||||
Test_Assert((dogRound == 0), "No Hellhound entities found but dogRound is not zero!");
|
||||
}
|
||||
};
|
50
source/server/tests/test_math.qc
Normal file
50
source/server/tests/test_math.qc
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
server/tests/test_math.qc
|
||||
|
||||
Unit test list for math functions. Mostly serves for testing the test infrastructure.
|
||||
|
||||
Copyright (C) 2021-2025 NZ:P Team
|
||||
|
||||
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; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
float(float condition, string message) Test_Assert;
|
||||
void(string message) Test_Skip;
|
||||
|
||||
//
|
||||
// Test_Math_ClampReturnsMin()
|
||||
// Asserts when sending a value less than min to clamp,
|
||||
// min is returned.
|
||||
//
|
||||
void() Test_Math_ClampReturnsMin =
|
||||
{
|
||||
float clamp_value = clamp(0, 1, 100);
|
||||
Test_Assert((clamp_value == 1), "Clamp returned incorrect value!");
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Math_ClampReturnsMax()
|
||||
// Asserts when sending a value greater than max to clamp,
|
||||
// max is returned.
|
||||
//
|
||||
void() Test_Math_ClampReturnsMax =
|
||||
{
|
||||
float clamp_value = clamp(900, 1, 100);
|
||||
Test_Assert((clamp_value == 100), "Clamp returned incorrect value!");
|
||||
};
|
56
source/server/tests/test_misc_model.qc
Normal file
56
source/server/tests/test_misc_model.qc
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
server/tests/test_misc_model.qc
|
||||
|
||||
Unit tests for misc_model entity
|
||||
|
||||
Copyright (C) 2021-2025 NZ:P Team
|
||||
|
||||
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; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
float(float condition, string message) Test_Assert;
|
||||
void(string message) Test_Skip;
|
||||
|
||||
//
|
||||
// Test_misc_model_ModelNotHiddenByDefault()
|
||||
// Spawns a misc_model with properties and validates
|
||||
// the model does not start hidden.
|
||||
// (https://github.com/nzp-team/nzportable/issues/996)
|
||||
//
|
||||
void() Test_misc_model_ModelNotHiddenByDefault =
|
||||
{
|
||||
entity miscmodel = spawn();
|
||||
entity old_self = self;
|
||||
self = miscmodel;
|
||||
|
||||
self.last_frame = 154;
|
||||
self.first_frame = 1;
|
||||
self.frame = 0;
|
||||
self.spawnflags = 6;
|
||||
self.speed = 0.1;
|
||||
self.model = "models/ai/zfull.mdl";
|
||||
self.classname = "misc_model";
|
||||
|
||||
misc_model();
|
||||
|
||||
Test_Assert((self.model != ""), "Model property started hidden!");
|
||||
|
||||
self = old_self;
|
||||
remove(miscmodel);
|
||||
};
|
155
source/server/tests/test_module.qc
Normal file
155
source/server/tests/test_module.qc
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
server/tests/test_main.qc
|
||||
|
||||
Test running and validation infrastructure for QuakeC unit tests.
|
||||
|
||||
Copyright (C) 2021-2025 NZ:P Team
|
||||
|
||||
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; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef FTE
|
||||
#ifdef QUAKEC_TEST
|
||||
|
||||
float total_tests_ran;
|
||||
float total_tests_passed;
|
||||
float total_tests_failed;
|
||||
float total_tests_skipped;
|
||||
float tests_starttime;
|
||||
float tests_endtime;
|
||||
|
||||
float test_skipped_notify;
|
||||
string skipped_message_buffer;
|
||||
|
||||
float test_failed_an_assert;
|
||||
string failed_message_buffer;
|
||||
|
||||
float(float condition, string message) Test_Assert =
|
||||
{
|
||||
if (condition == false) {
|
||||
failed_message_buffer = sprintf("%s[ERROR]: %s\n", failed_message_buffer, message);
|
||||
test_failed_an_assert = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
void(string message) Test_Skip =
|
||||
{
|
||||
test_skipped_notify = true;
|
||||
skipped_message_buffer = sprintf("[SKIP]: %s\n", message);
|
||||
}
|
||||
|
||||
void(void() test_func, string test_name) Test_Run =
|
||||
{
|
||||
print(sprintf("[INFO]: Running test [%s]..", test_name));
|
||||
test_func();
|
||||
|
||||
if (test_skipped_notify == true) {
|
||||
print("SKIP!\n");
|
||||
total_tests_skipped++;
|
||||
print(sprintf("%s", skipped_message_buffer));
|
||||
skipped_message_buffer = "";
|
||||
test_skipped_notify = false;
|
||||
total_tests_ran--;
|
||||
} else if (test_failed_an_assert == false) {
|
||||
print("PASS!\n");
|
||||
total_tests_passed++;
|
||||
} else {
|
||||
print("FAIL!\n");
|
||||
total_tests_failed++;
|
||||
print(sprintf("%s", failed_message_buffer));
|
||||
failed_message_buffer = "";
|
||||
test_failed_an_assert = false;
|
||||
}
|
||||
|
||||
total_tests_ran++;
|
||||
|
||||
print("\n");
|
||||
};
|
||||
|
||||
void() Test_PrintSummary =
|
||||
{
|
||||
print("====================== TEST SUMMARY ======================\n");
|
||||
print(sprintf("* Passed: %d\n* Failed: %d\n* Skipped: %d\n* Total Ran: %d\n", total_tests_passed, total_tests_failed, total_tests_skipped, total_tests_ran));
|
||||
print(sprintf("* %d%% Passing Grade\n", (total_tests_passed/total_tests_ran) * 100));
|
||||
print(sprintf("* %fs Total Runtime\n", tests_endtime));
|
||||
print("==================== END TEST SUMMARY ====================\n");
|
||||
localcmd("quit\n");
|
||||
};
|
||||
|
||||
//
|
||||
// Test Table
|
||||
// Add unit tests to this table for them to be
|
||||
// executed during Pull Request testing.
|
||||
//
|
||||
var struct {
|
||||
void() test_func;
|
||||
string test_name;
|
||||
} qc_unit_tests[] = {
|
||||
{ Test_Math_ClampReturnsMin, "Test_Math_ClampReturnsMin" },
|
||||
{ Test_Math_ClampReturnsMax, "Test_Math_ClampReturnsMax" },
|
||||
{ Test_Perks_QuickRevive_ValidateFields, "Test_Perks_QuickRevive_ValidateFields" },
|
||||
{ Test_Perks_JuggerNog_ValidateFields, "Test_Perks_JuggerNog_ValidateFields" },
|
||||
{ Test_Perks_SpeedCola_ValidateFields, "Test_Perks_SpeedCola_ValidateFields" },
|
||||
{ Test_Perks_DoubleTap_ValidateFields, "Test_Perks_DoubleTap_ValidateFields" },
|
||||
{ Test_Perks_StaminUp_ValidateFields, "Test_Perks_StaminUp_ValidateFields" },
|
||||
{ Test_Perks_PhDFlopper_ValidateFields, "Test_Perks_PhDFlopper_ValidateFields" },
|
||||
{ Test_Perks_DeadshotDaiquiri_ValidateFields, "Test_Perks_DeadshotDaiquiri_ValidateFields" },
|
||||
{ Test_Perks_Random_LegacyFields, "Test_Perks_Random_LegacyFields" },
|
||||
{ Test_Perks_MuleKick_ValidateFields, "Test_Perks_MuleKick_ValidateFields" },
|
||||
{ Test_Weapons_Gewehr_MagazineSize, "Test_Weapons_Gewehr_MagazineSize" },
|
||||
{ Test_Weapons_BowieKnife_RemovedAfterRespawn, "Test_Weapons_BowieKnife_RemovedAfterRespawn" },
|
||||
{ Test_Weapons_HoldTwoWeapons, "Test_Weapons_HoldTwoWeapons" },
|
||||
{ Test_Weapons_HoldThreeWeapons, "Test_Weapons_HoldThreeWeapons" },
|
||||
{ Test_Weapons_UpgradedSound, "Test_Weapons_UpgradedSound" },
|
||||
{ Test_Weapons_ShotgunPenetration, "Test_Weapons_ShotgunPenetration" },
|
||||
{ Test_Weapons_WunderWaffe_UpgradedReserve, "Test_Weapons_WunderWaffe_UpgradedReserve" },
|
||||
{ Test_Weapons_WunderWaffe_FireAtBarrel, "Test_Weapons_WunderWaffe_FireAtBarrel" },
|
||||
{ Test_WallWeapons_Message, "Test_WallWeapons_Message" },
|
||||
{ Test_WallWeapons_ActivatesAllTargets, "Test_WallWeapons_ActivatesAllTargets" },
|
||||
{ Test_Weapons_DualWield_ReloadLowReserveRightLeft, "Test_Weapons_DualWield_ReloadLowReserveRightLeft" },
|
||||
{ Test_Weapons_DualWield_ReloadLowReserveLeftRight, "Test_Weapons_DualWield_ReloadLowReserveLeftRight" },
|
||||
{ Test_misc_model_ModelNotHiddenByDefault, "Test_misc_model_ModelNotHiddenByDefault" },
|
||||
{ Test_AddScore_NonClient, "Test_AddScore_NonClient" },
|
||||
{ Test_AddScore_DamageTypes, "Test_AddScore_DamageTypes" },
|
||||
{ Test_AddScore_MysteryBoxLeave, "Test_AddScore_MysteryBoxLeave" },
|
||||
{ Test_AI_HellhoundsDetected, "Test_AI_HellhoundsDetected" }
|
||||
};
|
||||
|
||||
void() Test_RunAllTests =
|
||||
{
|
||||
if (tests_starttime != 0)
|
||||
return;
|
||||
|
||||
total_tests_ran = 0;
|
||||
total_tests_passed = 0;
|
||||
total_tests_failed = 0;
|
||||
|
||||
tests_starttime = gettime();
|
||||
for(int i = 0; i < qc_unit_tests.length; i++) {
|
||||
Test_Run(qc_unit_tests[i].test_func, qc_unit_tests[i].test_name);
|
||||
}
|
||||
tests_endtime = gettime();
|
||||
Test_PrintSummary();
|
||||
};
|
||||
|
||||
#endif // QUAKEC_TEST
|
||||
#endif // FTE
|
215
source/server/tests/test_perksacola.qc
Normal file
215
source/server/tests/test_perksacola.qc
Normal file
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
server/tests/test_perksacola.qc
|
||||
|
||||
Perk-A-Cola unit tests.
|
||||
|
||||
Copyright (C) 2021-2025 NZ:P Team
|
||||
|
||||
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; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
float(float condition, string message) Test_Assert;
|
||||
void(string message) Test_Skip;
|
||||
|
||||
//
|
||||
// Test_Perks_QuickRevive_ValidatePrice()
|
||||
// Spawns a Quick Revive machine and validates its
|
||||
// default fields.
|
||||
//
|
||||
void() Test_Perks_QuickRevive_ValidateFields =
|
||||
{
|
||||
entity machine = spawn();
|
||||
entity old_self = self;
|
||||
self = machine;
|
||||
|
||||
perk_revive();
|
||||
|
||||
Test_Assert((self.model == PERK_QUICKREVIVE_DEFAULT_MODEL), "Perk has incorrect model!");
|
||||
Test_Assert((self.cost == 500), "Perk has incorrect Solo cost!");
|
||||
Test_Assert((self.cost2 == 1500), "Perk has incorrect Co-Op cost!");
|
||||
|
||||
self = old_self;
|
||||
remove(machine);
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Perks_JuggerNog_ValidatePrice()
|
||||
// Spawns a Jugger-Nog machine and validates its
|
||||
// default fields.
|
||||
//
|
||||
void() Test_Perks_JuggerNog_ValidateFields =
|
||||
{
|
||||
entity machine = spawn();
|
||||
entity old_self = self;
|
||||
self = machine;
|
||||
|
||||
perk_juggernog();
|
||||
|
||||
Test_Assert((self.model == PERK_JUGGERNOG_DEFAULT_MODEL), "Perk has incorrect model!");
|
||||
Test_Assert((self.cost == 2500), "Perk has incorrect Solo cost!");
|
||||
Test_Assert((self.cost2 == 2500), "Perk has incorrect Co-Op cost!");
|
||||
|
||||
self = old_self;
|
||||
remove(machine);
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Perks_SpeedCola_ValidatePrice()
|
||||
// Spawns a Speed Cola machine and validates its
|
||||
// default fields.
|
||||
//
|
||||
void() Test_Perks_SpeedCola_ValidateFields =
|
||||
{
|
||||
entity machine = spawn();
|
||||
entity old_self = self;
|
||||
self = machine;
|
||||
|
||||
perk_speed();
|
||||
|
||||
Test_Assert((self.model == PERK_SPEEDCOLA_DEFAULT_MODEL), "Perk has incorrect model!");
|
||||
Test_Assert((self.cost == 3000), "Perk has incorrect Solo cost!");
|
||||
Test_Assert((self.cost2 == 3000), "Perk has incorrect Co-Op cost!");
|
||||
|
||||
self = old_self;
|
||||
remove(machine);
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Perks_DoubleTap_ValidateFields()
|
||||
// Spawns a Double Tap machine and validates its
|
||||
// default fields.
|
||||
//
|
||||
void() Test_Perks_DoubleTap_ValidateFields =
|
||||
{
|
||||
entity machine = spawn();
|
||||
entity old_self = self;
|
||||
self = machine;
|
||||
|
||||
perk_double();
|
||||
|
||||
Test_Assert((self.model == PERK_DOUBLETAP_DEFAULT_MODEL), "Perk has incorrect model!");
|
||||
Test_Assert((self.cost == 2000), "Perk has incorrect Solo cost!");
|
||||
Test_Assert((self.cost2 == 2000), "Perk has incorrect Co-Op cost!");
|
||||
|
||||
self = old_self;
|
||||
remove(machine);
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Perks_StaminUp_ValidateFields()
|
||||
// Spawns a Stamin-Up machine and validates its
|
||||
// default fields.
|
||||
//
|
||||
void() Test_Perks_StaminUp_ValidateFields =
|
||||
{
|
||||
entity machine = spawn();
|
||||
entity old_self = self;
|
||||
self = machine;
|
||||
|
||||
perk_staminup();
|
||||
|
||||
Test_Assert((self.model == PERK_STAMINUP_DEFAULT_MODEL), "Perk has incorrect model!");
|
||||
Test_Assert((self.cost == 2000), "Perk has incorrect Solo cost!");
|
||||
Test_Assert((self.cost2 == 2000), "Perk has incorrect Co-Op cost!");
|
||||
|
||||
self = old_self;
|
||||
remove(machine);
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Perks_PhDFlopper_ValidateFields()
|
||||
// Spawns a PhD Flopper machine and validates its
|
||||
// default fields.
|
||||
//
|
||||
void() Test_Perks_PhDFlopper_ValidateFields =
|
||||
{
|
||||
entity machine = spawn();
|
||||
entity old_self = self;
|
||||
self = machine;
|
||||
|
||||
perk_flopper();
|
||||
|
||||
Test_Assert((self.model == PERK_PHDFLOPPER_DEFAULT_MODEL), "Perk has incorrect model!");
|
||||
Test_Assert((self.cost == 2000), "Perk has incorrect Solo cost!");
|
||||
Test_Assert((self.cost2 == 2000), "Perk has incorrect Co-Op cost!");
|
||||
|
||||
self = old_self;
|
||||
remove(machine);
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Perks_DeadshotDaiquiri_ValidateFields()
|
||||
// Spawns a Deadshot Daiquiri machine and validates its
|
||||
// default fields.
|
||||
//
|
||||
void() Test_Perks_DeadshotDaiquiri_ValidateFields =
|
||||
{
|
||||
entity machine = spawn();
|
||||
entity old_self = self;
|
||||
self = machine;
|
||||
|
||||
perk_deadshot();
|
||||
|
||||
Test_Assert((self.model == PERK_DEADSHOT_DEFAULT_MODEL), "Perk has incorrect model!");
|
||||
Test_Assert((self.cost == 1500), "Perk has incorrect Solo cost!");
|
||||
Test_Assert((self.cost2 == 1500), "Perk has incorrect Co-Op cost!");
|
||||
|
||||
self = old_self;
|
||||
remove(machine);
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Perks_MuleKick_ValidateFields()
|
||||
// Spawns a Deadshot Daiquiri machine and validates its
|
||||
// default fields.
|
||||
//
|
||||
void() Test_Perks_MuleKick_ValidateFields =
|
||||
{
|
||||
entity machine = spawn();
|
||||
entity old_self = self;
|
||||
self = machine;
|
||||
|
||||
perk_mule();
|
||||
|
||||
Test_Assert((self.model == PERK_MULEKICK_DEFAULT_MODEL), "Perk has incorrect model!");
|
||||
Test_Assert((self.cost == 4000), "Perk has incorrect Solo cost!");
|
||||
Test_Assert((self.cost2 == 4000), "Perk has incorrect Co-Op cost!");
|
||||
|
||||
self = old_self;
|
||||
remove(machine);
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Perks_Random_LegacyFields()
|
||||
// Attempts to spawn a random Perk-A-Cola
|
||||
// with the perk_random fields using
|
||||
// legacy data.
|
||||
// (https://github.com/nzp-team/nzportable/issues/664)
|
||||
//
|
||||
void() Test_Perks_Random_LegacyFields =
|
||||
{
|
||||
entity random = spawn();
|
||||
entity old_self = self;
|
||||
self = random;
|
||||
self.spawnflags = 240;
|
||||
perk_random();
|
||||
self = old_self;
|
||||
|
||||
remove(random);
|
||||
};
|
113
source/server/tests/test_score.qc
Normal file
113
source/server/tests/test_score.qc
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
server/tests/test_score.qc
|
||||
|
||||
Unit tests for score system
|
||||
|
||||
Copyright (C) 2021-2025 NZ:P Team
|
||||
|
||||
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; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
float(float condition, string message) Test_Assert;
|
||||
void(string message) Test_Skip;
|
||||
|
||||
//
|
||||
// Test_AddScore_NonClient()
|
||||
// Attempts to give points to a non-client.
|
||||
// (https://github.com/nzp-team/nzportable/issues/783)
|
||||
//
|
||||
void() Test_AddScore_NonClient =
|
||||
{
|
||||
entity some_ent = spawn();
|
||||
Player_AddScore(some_ent, 10, false);
|
||||
remove(some_ent);
|
||||
};
|
||||
|
||||
//
|
||||
// Test_AddScore_DamageTypes()
|
||||
// Asserts we are giving correct amount
|
||||
// of score for every AI damage type.
|
||||
// (https://github.com/nzp-team/nzportable/issues/776)
|
||||
//
|
||||
void() Test_AddScore_DamageTypes =
|
||||
{
|
||||
float styles[] = {
|
||||
DMG_TYPE_HEADSHOT,
|
||||
DMG_TYPE_MELEE,
|
||||
DMG_TYPE_TESLA,
|
||||
DMG_TYPE_FLAMETHROWER,
|
||||
DMG_TYPE_GRENADE,
|
||||
DMG_TYPE_EXPLOSIVE,
|
||||
DMG_TYPE_LOWERTORSO,
|
||||
DMG_TYPE_UPPERTORSO
|
||||
};
|
||||
|
||||
float scores[] = {
|
||||
DMG_SCORE_HEADSHOT,
|
||||
DMG_SCORE_MELEE,
|
||||
DMG_SCORE_GRENADE,
|
||||
DMG_SCORE_GRENADE,
|
||||
DMG_SCORE_GRENADE,
|
||||
DMG_SCORE_EXPLOSIVE,
|
||||
DMG_SCORE_LOWERTORSO,
|
||||
DMG_SCORE_UPPERTORSO
|
||||
};
|
||||
|
||||
for (float i = 0; i < styles.length; i++) {
|
||||
float score_pre = self.points;
|
||||
|
||||
DieHandler(self, styles[i]);
|
||||
|
||||
float score_post = self.points;
|
||||
float score_delta = score_post - score_pre;
|
||||
|
||||
Test_Assert((score_delta == scores[i]), sprintf("Unexpected score earned, expected [%d] but got [%d]!", scores[i], score_delta));
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Test_AddScore_MysteryBoxLeave()
|
||||
// Asserts we get exact amount of points
|
||||
// back when the Mystery Box attempts
|
||||
// to leave.
|
||||
// (https://github.com/nzp-team/nzportable/issues/775)
|
||||
//
|
||||
void() Test_AddScore_MysteryBoxLeave =
|
||||
{
|
||||
precache_sound("sounds/misc/giggle.wav");
|
||||
|
||||
float score_pre = self.points;
|
||||
|
||||
entity mystery_box_ent = spawn();
|
||||
entity owner_ent = spawn();
|
||||
entity old_self = self;
|
||||
|
||||
self = mystery_box_ent;
|
||||
mystery_box();
|
||||
self.owner = owner_ent;
|
||||
self.owner.owner = old_self;
|
||||
MBOX_PresentTeddy();
|
||||
self = old_self;
|
||||
|
||||
float score_post = self.points;
|
||||
Test_Assert((score_post - score_pre == mystery_box_cost), "Unexpected points earned!");
|
||||
|
||||
remove(mystery_box_ent);
|
||||
remove(owner_ent);
|
||||
};
|
295
source/server/tests/test_weapons.qc
Normal file
295
source/server/tests/test_weapons.qc
Normal file
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
server/tests/test_weapons.qc
|
||||
|
||||
Weapon related unit tests.
|
||||
|
||||
Copyright (C) 2021-2025 NZ:P Team
|
||||
|
||||
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; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
float(float condition, string message) Test_Assert;
|
||||
void(string message) Test_Skip;
|
||||
|
||||
//
|
||||
//
|
||||
// Weapon System
|
||||
//
|
||||
//
|
||||
|
||||
//
|
||||
// Test_Weapons_Gewehr_MagazineSize()
|
||||
// Asserts the Gewehr and it's Pack-A-Punched
|
||||
// form have the correct magazine sizes.
|
||||
// (https://github.com/nzp-team/nzportable/issues/1102)
|
||||
//
|
||||
void() Test_Weapons_Gewehr_MagazineSize =
|
||||
{
|
||||
Test_Assert((getWeaponMag(W_GEWEHR) == 10), "Gewehr has incorrect magazine size!");
|
||||
Test_Assert((getWeaponMag(W_COMPRESSOR) == 12), "Upgraded Gewehr has incorrect magazine size!");
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Weapons_DualWield_ReloadLowReserveRightLeft()
|
||||
// Asserts if we are attempting to reload a Dual Wield
|
||||
// weapon while the reserve is too small to fill both
|
||||
// mags, that we do not give out more ammo than intended.
|
||||
// This triggers the Right side first, then Left.
|
||||
// (https://github.com/nzp-team/nzportable/issues/1096)
|
||||
//
|
||||
void() Test_Weapons_DualWield_ReloadLowReserveRightLeft =
|
||||
{
|
||||
Weapon_RemoveWeapon(0);
|
||||
Weapon_GiveWeapon(W_BIATCH, 0, 0);
|
||||
|
||||
self.weapons[0].weapon_magazine = 3;
|
||||
self.weapons[0].weapon_magazine_left = 1;
|
||||
self.weapons[0].weapon_reserve = 7;
|
||||
|
||||
W_Give_Ammo(S_RIGHT);
|
||||
W_Give_Ammo(S_LEFT);
|
||||
|
||||
Test_Assert((self.weapons[0].weapon_magazine == 6), sprintf("Expected [6] for right magazine size, got [%d]!", self.weapons[0].weapon_magazine));
|
||||
Test_Assert((self.weapons[0].weapon_magazine_left == 5), sprintf("Expected [5] for left magazine size, got [%d]!", self.weapons[0].weapon_magazine_left));
|
||||
Test_Assert((self.weapons[0].weapon_reserve == 0), sprintf("Expected [0] for reserve size, got [%d]!", self.weapons[0].weapon_reserve));
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Weapons_DualWield_ReloadLowReserveLeftRight()
|
||||
// Asserts if we are attempting to reload a Dual Wield
|
||||
// weapon while the reserve is too small to fill both
|
||||
// mags, that we do not give out more ammo than intended.
|
||||
// This triggers the Right side first, then Left.
|
||||
// (https://github.com/nzp-team/nzportable/issues/1096)
|
||||
//
|
||||
void() Test_Weapons_DualWield_ReloadLowReserveLeftRight =
|
||||
{
|
||||
Weapon_RemoveWeapon(0);
|
||||
Weapon_GiveWeapon(W_BIATCH, 0, 0);
|
||||
|
||||
self.weapons[0].weapon_magazine = 3;
|
||||
self.weapons[0].weapon_magazine_left = 1;
|
||||
self.weapons[0].weapon_reserve = 7;
|
||||
|
||||
W_Give_Ammo(S_LEFT);
|
||||
W_Give_Ammo(S_RIGHT);
|
||||
|
||||
Test_Assert((self.weapons[0].weapon_magazine == 5), sprintf("Expected [5] for right magazine size, got [%d]!", self.weapons[0].weapon_magazine));
|
||||
Test_Assert((self.weapons[0].weapon_magazine_left == 6), sprintf("Expected [6] for left magazine size, got [%d]!", self.weapons[0].weapon_magazine_left));
|
||||
Test_Assert((self.weapons[0].weapon_reserve == 0), sprintf("Expected [0] for reserve size, got [%d]!", self.weapons[0].weapon_reserve));
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Weapons_BowieKnife_RemovedAfterRespawn()
|
||||
// Asserts that upon respawning a client loses the
|
||||
// Bowie Knife.
|
||||
// (https://github.com/nzp-team/nzportable/issues/922)
|
||||
//
|
||||
void() Test_Weapons_BowieKnife_RemovedAfterRespawn =
|
||||
{
|
||||
self.has_bowie_knife = true;
|
||||
PlayerSpawn();
|
||||
Test_Assert((self.has_bowie_knife == false), "Client still has Bowie Knife!");
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Weapons_HoldTwoWeapons()
|
||||
// Asserts we can hold more than just a single
|
||||
// weapon.
|
||||
// (https://github.com/nzp-team/nzportable/issues/786)
|
||||
//
|
||||
void() Test_Weapons_HoldTwoWeapons =
|
||||
{
|
||||
Weapon_GiveWeapon(W_COLT, 0, 0);
|
||||
Weapon_GiveWeapon(W_GEWEHR, 0, 0);
|
||||
|
||||
Test_Assert((self.weapons[0].weapon_id != 0), "No weapon in slot zero!");
|
||||
Test_Assert((self.weapons[1].weapon_id != 0), "No weapon in slot one!");
|
||||
|
||||
Weapon_RemoveWeapon(1);
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Weapons_HoldThreeWeapons()
|
||||
// Gives the client Mule Kick and asserts we can
|
||||
// hold three weapons.
|
||||
//
|
||||
void() Test_Weapons_HoldThreeWeapons =
|
||||
{
|
||||
GivePerk(P_MULE);
|
||||
|
||||
Weapon_GiveWeapon(W_COLT, 0, 0);
|
||||
Weapon_GiveWeapon(W_GEWEHR, 0, 0);
|
||||
Weapon_GiveWeapon(W_KAR, 0, 0);
|
||||
|
||||
Test_Assert((self.weapons[0].weapon_id != 0), "No weapon in slot zero!");
|
||||
Test_Assert((self.weapons[1].weapon_id != 0), "No weapon in slot one!");
|
||||
Test_Assert((self.weapons[2].weapon_id != 0), "No weapon in slot two!");
|
||||
|
||||
Weapon_RemoveWeapon(1);
|
||||
Weapon_RemoveWeapon(2);
|
||||
self.perks = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Weapons_UpgradedSound()
|
||||
// Validates certain weapons are set to not
|
||||
// play an upgraded sound.
|
||||
//
|
||||
void() Test_Weapons_UpgradedSound =
|
||||
{
|
||||
float weapon_list[] = { W_DG3, W_PORTER, W_FIW };
|
||||
|
||||
for (float i = 0; i < weapon_list.length; i++) {
|
||||
Test_Assert((WepDef_DoesNotPlayUpgradedSound(weapon_list[i]) == true), sprintf("Weapon [%s] plays an upgraded sound!", GetWeaponName(weapon_list[i])));
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Weapons_ShotgunPenetration()
|
||||
// Validates shotgun penetration is set
|
||||
// correctly.
|
||||
// (https://github.com/nzp-team/nzportable/issues/652)
|
||||
//
|
||||
void() Test_Weapons_ShotgunPenetration =
|
||||
{
|
||||
float weapon_list[] = { W_DB, W_BORE, W_SAWNOFF, W_SNUFF, W_TRENCH, W_GUT };
|
||||
|
||||
for (float i = 0; i < weapon_list.length; i++) {
|
||||
Test_Assert((getWeaponPenetration(weapon_list[i], 2) != 0), sprintf("Weapon [%s] not correctly penetrating!", GetWeaponName(weapon_list[i])));
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Weapons_WunderWaffe_UpgradedReserve()
|
||||
// Validates correct reserve ammo count for DG-3.
|
||||
// (https://github.com/nzp-team/nzportable/issues/651)
|
||||
//
|
||||
void() Test_Weapons_WunderWaffe_UpgradedReserve =
|
||||
{
|
||||
Test_Assert(getWeaponAmmo(W_DG3) == 30, "Incorrect reserve ammo!");
|
||||
};
|
||||
|
||||
//
|
||||
// Test_Weapons_WunderWaffe_FireAtBarrel()
|
||||
// Simulates firing the DG-2 at an explosive barrel
|
||||
// and validates it does not count as a kill and
|
||||
// does not award points.
|
||||
// (https://github.com/nzp-team/nzportable/issues/584)
|
||||
//
|
||||
void() Test_Weapons_WunderWaffe_FireAtBarrel =
|
||||
{
|
||||
Test_Skip("Skipped while facing odd traceline behavior");
|
||||
#if 0
|
||||
float kills_pre = self.kills;
|
||||
float score_pre = self.points;
|
||||
|
||||
makevectors(self.angles);
|
||||
|
||||
entity barrel = spawn();
|
||||
entity old_self = self;
|
||||
self = barrel;
|
||||
setorigin(self, old_self.origin + (v_forward * 50) + '0 0 16');
|
||||
explosive_barrel();
|
||||
self = old_self;
|
||||
|
||||
Weapon_GiveWeapon(W_TESLA, 0, 0);
|
||||
W_FireTesla();
|
||||
|
||||
float kills_post = self.kills;
|
||||
float score_post = self.points;
|
||||
|
||||
Test_Assert((kills_pre == kills_post), "Explosive barrel counted as kill!");
|
||||
Test_Assert((score_pre == score_post), "Explosive barrel earned score!");
|
||||
#endif
|
||||
};
|
||||
|
||||
//
|
||||
//
|
||||
// Wall Weapons
|
||||
//
|
||||
//
|
||||
|
||||
//
|
||||
// Test_WallWeapons_Message()
|
||||
// Asserts a written message field gets removed
|
||||
// from a buy_weapon()
|
||||
//
|
||||
void() Test_WallWeapons_Message =
|
||||
{
|
||||
entity weapon = spawn();
|
||||
entity old_self = self;
|
||||
self = weapon;
|
||||
|
||||
self.message = "test";
|
||||
|
||||
buy_weapon();
|
||||
|
||||
Test_Assert((self.message == ""), "Message field was not removed!");
|
||||
|
||||
self = old_self;
|
||||
remove(weapon);
|
||||
};
|
||||
|
||||
//
|
||||
// Test_WallWeapons_ActivatesAllTargets()
|
||||
// Validates that when a buy_weapon entity
|
||||
// uses its targets, all 8 are activated.
|
||||
// (https://github.com/nzp-team/nzportable/issues/961)
|
||||
//
|
||||
void() Test_WallWeapons_ActivatesAllTargets =
|
||||
{
|
||||
float i;
|
||||
|
||||
entity weapon = spawn();
|
||||
entity old_self = self;
|
||||
entity targets[8];
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
targets[i] = spawn();
|
||||
targets[i].health = 2;
|
||||
targets[i].targetname = sprintf("test_target_%d", i);
|
||||
|
||||
self = targets[i];
|
||||
game_counter();
|
||||
}
|
||||
|
||||
self = weapon;
|
||||
self.target = "test_target_0";
|
||||
self.target2 = "test_target_1";
|
||||
self.target3 = "test_target_2";
|
||||
self.target4 = "test_target_3";
|
||||
self.target5 = "test_target_4";
|
||||
self.target6 = "test_target_5";
|
||||
self.target7 = "test_target_6";
|
||||
self.target8 = "test_target_7";
|
||||
buy_weapon();
|
||||
SUB_UseTargets();
|
||||
|
||||
for(i = 0; i < 8; i++) {
|
||||
Test_Assert((targets[i].frags == 1), sprintf("Target #%d did not increment!", i));
|
||||
remove(targets[i]);
|
||||
}
|
||||
|
||||
self = old_self;
|
||||
remove(weapon);
|
||||
};
|
||||
|
84
testing/run_unit_tests.sh
Normal file
84
testing/run_unit_tests.sh
Normal file
|
@ -0,0 +1,84 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Nazi Zombies: Portable
|
||||
# QuakeC Unit test runner.
|
||||
# ----
|
||||
# This is intended to be used via a Docker
|
||||
# container running ubuntu:24.10.
|
||||
#
|
||||
set -o errexit
|
||||
|
||||
# tzdata will try to display an interactive install prompt by
|
||||
# default, so make sure we define our system as non-interactive.
|
||||
export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true
|
||||
|
||||
WORKING_DIRECTORY="/working"
|
||||
OUTPUT_LOG="${WORKING_DIRECTORY}/run.log"
|
||||
REPO_PWD=$(pwd)
|
||||
|
||||
function setup_container()
|
||||
{
|
||||
echo "[INFO]: Installing dependancies.."
|
||||
apt update -y
|
||||
apt install libsdl2-dev wget zip python3 python3-pip -y
|
||||
wget https://raw.githubusercontent.com/nzp-team/QCHashTableGenerator/main/requirements.txt
|
||||
pip install -r requirements.txt --break-system-packages
|
||||
rm requirements.txt
|
||||
mkdir -p "${WORKING_DIRECTORY}"
|
||||
}
|
||||
|
||||
function download_nzp()
|
||||
{
|
||||
echo "[INFO]: Obtaining latest Nazi Zombies: Portable Linux x86_64 release.."
|
||||
cd "${WORKING_DIRECTORY}"
|
||||
wget https://github.com/nzp-team/nzportable/releases/download/nightly/nzportable-linux64.zip
|
||||
mkdir nzportable-linux64
|
||||
unzip nzportable-linux64.zip -d nzportable-linux64/
|
||||
chmod +x nzportable-linux64/nzportable64-sdl
|
||||
}
|
||||
|
||||
function build_quakec()
|
||||
{
|
||||
echo "[INFO]: Building QuakeC.."
|
||||
cd "${REPO_PWD}/tools"
|
||||
local cmd="./qc-compiler-gnu.sh --test-mode"
|
||||
${cmd}
|
||||
|
||||
echo "[INFO]: Moving QuakeC to game download.."
|
||||
cp "${REPO_PWD}/build/fte/qwprogs.dat" "${WORKING_DIRECTORY}/nzportable-linux64/nzp/"
|
||||
}
|
||||
|
||||
function run_test()
|
||||
{
|
||||
local game_crashed="0"
|
||||
touch "${OUTPUT_LOG}"
|
||||
|
||||
echo "[INFO]: Running unit tests.."
|
||||
cd "${WORKING_DIRECTORY}/nzportable-linux64/"
|
||||
local cmd="./nzportable64-sdl +map nzp_warehouse +vid_renderer headless"
|
||||
${cmd} | tee "${OUTPUT_LOG}"
|
||||
|
||||
failed_count=$( cat "${OUTPUT_LOG}" | grep "* Failed: " | cut -c 11- || game_crashed="1" )
|
||||
|
||||
if [[ "${game_crashed}" -ne "0" ]]; then
|
||||
echo "[ERROR]: Game crashed, no condump generated! Bailing!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${failed_count}" -ne "0" ]]; then
|
||||
echo "[ERROR]: [${failed_count}] failures occurred while running unit tests!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[INFO]: UNIT TEST PASSED."
|
||||
}
|
||||
|
||||
function main()
|
||||
{
|
||||
setup_container;
|
||||
download_nzp;
|
||||
build_quakec;
|
||||
run_test;
|
||||
}
|
||||
|
||||
main;
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e errexit
|
||||
set -o errexit
|
||||
|
||||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)
|
||||
QUAKEC_ROOT=$(dirname "${SCRIPT_DIR}")
|
||||
|
@ -13,6 +13,14 @@ if [[ "${OSTYPE}" == "darwin"* ]]; then
|
|||
FTEQCC="fteqcc-cli-mac"
|
||||
fi
|
||||
|
||||
# Arguments
|
||||
while true; do
|
||||
case "$1" in
|
||||
-t | --test-mode ) TEST_FLAG="-DQUAKEC_TEST"; shift 1 ;;
|
||||
* ) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
function setup()
|
||||
{
|
||||
cd "${QUAKEC_ROOT}"
|
||||
|
@ -53,7 +61,7 @@ function main()
|
|||
{
|
||||
setup;
|
||||
compile_progs "csqc" "FTE CSQC" "-DFTE -Wall"
|
||||
compile_progs "ssqc" "FTE SSQC" "-O3 -DFTE -Wall"
|
||||
compile_progs "ssqc" "FTE SSQC" "-O3 -DFTE ${TEST_FLAG} -Wall"
|
||||
compile_progs "menu" "FTE MenuQC" "-O3 -DFTE -Wall"
|
||||
compile_progs "ssqc" "Vril SSQC" "-O3 -Wall"
|
||||
exit ${RC}
|
||||
|
|
Loading…
Reference in a new issue