TEST_F(GameTest, CountSpawnpoints) { const char* filterId = TEST_GetStringProperty("mapdef-id"); const mapDef_t* md; Cvar_Set("rm_drop", "+craft_drop_herakles"); /* use a known seed to reproduce an error */ unsigned int seed; if (TEST_ExistsProperty("mapdef-seed")) { seed = TEST_GetLongProperty("mapdef-seed"); } else { seed = (unsigned int) time(nullptr); } srand(seed); MapDef_Foreach(md) { if (md->mapTheme[0] == '.') continue; if (filterId && !Q_streq(filterId, md->id)) continue; if (md->aircraft) /* if the mapdef has a list of dropships, let's assume they bring their own spawnpoints */ continue; Com_Printf("testCountSpawnpoints: Mapdef %s (seed %u)\n", md->id, seed); const char* asmName = (const char*)LIST_GetByIdx(md->params, 0); SV_Map(true, md->mapTheme, asmName, false); const int spawnPoints = static_cast<int>(level.num_spawnpoints[TEAM_PHALANX]); Com_Printf("Map: %s Mapdef %s Spawnpoints: %i\n", md->mapTheme, md->id, spawnPoints); ASSERT_TRUE(level.num_spawnpoints[TEAM_PHALANX] >= 12) << "Map " << md->mapTheme << " only " << spawnPoints << " spawnpoints"; } }
void GameTest::testCountSpawnpointsForMapWithAssemblyAndAircraftAndUfo(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft, const char *ufo) { if (verbose && ufo) { std::cout << "[ ] adding test parameter: ufo " << ufo << std::endl; Com_Printf("CountSpawnpoints - adding test parameter: ufo %s\n", ufo); } /* The ufocrash map is a special one. The mapdef should not define single- nor multiplayer mode. It uses one assembly for each ufo defined in the mapdef, where the assembly name is equal the name of the UFO. */ if (Q_streq(md->id, "ufocrash")) { testCountSpawnpointsForMapInSingleplayerMode(verbose, md, ufo, aircraft, ufo); return; } /* Check if we are manually testing a certain gamemode. */ if (TEST_ExistsProperty("mode")) { const char *mode = TEST_GetStringProperty("mode"); if (Q_streq(mode, "sp")) { if (md->singleplayer || md->campaign) { testCountSpawnpointsForMapInSingleplayerMode(verbose, md, asmName, aircraft, ufo); } else { Com_Printf("CountSpawnpoints - error: Gamemode not defined in mapdef: %s\n", mode); ADD_FAILURE() << "Error: Gamemode not defined in mapdef: " << mode; } } else if (Q_streq(mode, "mp")) { if (md->multiplayer) { testCountSpawnpointsForMapInMultiplayerMode(verbose, md, asmName, aircraft, ufo); } else { Com_Printf("CountSpawnpoints - error: Gamemode not defined in mapdef: %s\n", mode); ADD_FAILURE() << "Error: Gamemode not defined in mapdef: " << mode; } } else { Com_Printf("CountSpawnpoints - error: Not a valid gamemode: %s\n", mode); ADD_FAILURE() << "Error: Not a valid gamemode: " << mode; } } else { /* Test every gamemode defined in the mapdef. */ if (md->singleplayer || md->campaign) { testCountSpawnpointsForMapInSingleplayerMode(verbose, md, asmName, aircraft, ufo); } if (md->multiplayer) { testCountSpawnpointsForMapInMultiplayerMode(verbose, md, asmName, aircraft, ufo); } } }
void GameTest::testCountSpawnpointsForMapWithAssemblyAndAircraft(bool verbose, const mapDef_t *md, const char *asmName, const char *aircraft) { if (verbose && aircraft) { std::cout << "[ ] adding test parameter: aircraft " << aircraft << std::endl; Com_Printf("CountSpawnpoints - adding test parameter: aircraft %s\n", aircraft); } /* Check if we are manually testing a certain UFO type. */ if (TEST_ExistsProperty("ufo")) { const char *ufo = TEST_GetStringProperty("ufo"); int tested = 0; LIST_Foreach(md->ufos, const char, s) { if (Q_streq(ufo, s)) { Cvar_Set("rm_ufo", "%s", Com_GetRandomMapAssemblyNameForCraft(ufo)); testCountSpawnpointsForMapWithAssemblyAndAircraftAndUfo(verbose, md, asmName, aircraft, ufo); tested += 1; } } if (tested < 1) { Com_Printf("CountSpawnpoints - error: Not a valid UFO id: %s\n", ufo); ADD_FAILURE() << "Error: Not a valid ufo id: " << ufo; } } else if (LIST_IsEmpty(md->ufos)) {
/** * @brief This test cycles through the list of map definitions found in the maps.ufo script * and tries to find surfaces to stand on with no sound assigned to them. * * This test takes too long to be run every time testall is run. So it's set up almost like a game: * After 5 maps (the first of them is fully checked) with missing sounds, the test stops. * If we manage to 'clean' one of those 5 maps, the next map will show up in the next run. */ TEST_F(FootStepTest, DISABLED_MapDefsFootSteps) { const char* filterId = TEST_GetStringProperty("mapdef-id"); const mapDef_t* md; int mapCount = 0; // the number of maps read int badMapCount = 0; const int skipCount = 20; // to skip the first n mapDefs const int badMapCountMax = 25; // # of maps with missing sounds before this test stops const int mapCountMax = 150; // should of cause be higher than skip + bad const int texCountMax = 30; char texNames[texCountMax][MAX_QPATH]; bool done = false; OBJZERO(texNames); ASSERT_TRUE(csi.numMDs > 0); MapDef_Foreach(md) { if (md->mapTheme[0] == '.') continue; if (filterId && !Q_streq(filterId, md->id)) continue; mapCount++; if (mapCount <= skipCount) continue; /* use a known seed to reproduce an error */ unsigned int seed; if (TEST_ExistsProperty("mapdef-seed")) { seed = TEST_GetLongProperty("mapdef-seed"); } else { seed = (unsigned int) time(nullptr); } srand(seed); int count = 0; Com_Printf("testMapDefsFootSteps: Mapdef %s (seed %u)\n", md->id, seed); const char* asmName = (const char*)LIST_GetByIdx(md->params, 0); SV_Map(true, md->mapTheme, asmName); /* now that we have loaded the map, check all cells for walkable places */ GridBox mBox(sv->mapData.mapBox); // test ALL the cells #if !FOOTSTEPS_FULL if (mapCount >= skipCount + 4) { // after the first 4 maps, reduce the testing area const pos3_t center = {148, 128, 0}; mBox.set(center, center); // the box on the map we're testing mBox.expandXY(10); // just test a few cells around the center of the map mBox.maxs[2] = 2; // and 3 levels high } #endif mBox.clipToMaxBoundaries(); for (int x = mBox.getMinX(); x <= mBox.getMaxX() && !done; x++) { for (int y = mBox.getMinY(); y <= mBox.getMaxY() && !done; y++) { for (int z = mBox.getMinZ(); z <= mBox.getMaxZ(); z++) { const int floor = sv->mapData.routing.getFloor(1, x, y, z); if (floor < 0) // if we have a floor in that cell continue; const AABB noBox(vec3_origin, vec3_origin); // we're doing a point-trace const pos3_t cellPos = {(pos_t)x, (pos_t)y, (pos_t)z}; // the cell in question vec3_t from, to; PosToVec(cellPos, from); // the center of the cell VectorCopy(from, to); // also base for the endpoint of the trace from[2] -= UNIT_HEIGHT / 2; // bottom of the cell from[2] += (floor + 2) * QUANT; // add the height of the floor plus 2 QUANTS to[2] -= 2 * UNIT_HEIGHT; // we should really hit the ground with this const trace_t trace = SV_Trace(Line(from, to), noBox, nullptr, MASK_SOLID); if (!trace.surface) continue; const char* snd = SV_GetFootstepSound(trace.surface->name); if (snd) continue; for (int i = 0; i < texCountMax; ++i) { if (!texNames[i][0]) { // found a free slot ? Q_strncpyz(texNames[i], trace.surface->name, sizeof(texNames[i])); count++; break; } if (Q_streq(trace.surface->name, texNames[i])) // already there ? break; } if (count > texCountMax) { done = true; break; // the z-loop } } } } if (!texNames[0][0]) { Com_Printf("In map %s, asm %s: Nothing detected\n", md->mapTheme, asmName); } else { ++badMapCount; for (int i = 0; i < texCountMax; ++i) { if (texNames[i][0]) { Com_Printf("In map %s, asm %s: No sound for: %s\n", md->mapTheme, asmName, texNames[i]); } } } OBJZERO(texNames); SV_ShutdownGameProgs(); if (done || mapCount >= mapCountMax || badMapCount >= badMapCountMax) break; } }