Pull out blocklist_driver.cpp and unit test it

This commit is contained in:
def 2020-11-06 18:18:55 +01:00
parent 5c79e9aa80
commit 3b90f97aa5
6 changed files with 104 additions and 83 deletions

View file

@ -1644,6 +1644,8 @@ if(CLIENT)
set_src(ENGINE_CLIENT GLOB src/engine/client
backend_sdl.cpp
backend_sdl.h
blocklist_driver.cpp
blocklist_driver.h
client.cpp
client.h
demoedit.cpp
@ -2114,6 +2116,7 @@ if(GTEST_FOUND OR DOWNLOAD_GTEST)
set_src(TESTS GLOB src/test
aio.cpp
bezier.cpp
blocklist_driver.cpp
color.cpp
csv.cpp
datafile.cpp
@ -2135,6 +2138,8 @@ if(GTEST_FOUND OR DOWNLOAD_GTEST)
unix.cpp
)
set(TESTS_EXTRA
src/engine/client/blocklist_driver.cpp
src/engine/client/blocklist_driver.h
src/engine/server/name_ban.cpp
src/engine/server/name_ban.h
src/game/server/teehistorian.cpp

View file

@ -3754,7 +3754,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderQuadContainerAsSpriteMultipl
// ------------ CCommandProcessorFragment_SDL
static void ParseVersionString(const GLubyte *pStr, int &VersionMajor, int &VersionMinor, int &VersionPatch)
static void ParseVersionString(const char *pStr, int &VersionMajor, int &VersionMinor, int &VersionPatch)
{
if(pStr)
{
@ -3765,12 +3765,12 @@ static void ParseVersionString(const GLubyte *pStr, int &VersionMajor, int &Vers
bool LastWasNumber = false;
while(*pStr && TotalNumbersPassed < 3)
{
if(*pStr >= (GLubyte)'0' && *pStr <= (GLubyte)'9')
if(*pStr >= '0' && *pStr <= '9')
{
aCurNumberStr[CurNumberStrLen++] = (char)*pStr;
LastWasNumber = true;
}
else if(LastWasNumber && (*pStr == (GLubyte)'.' || *pStr == (GLubyte)' ' || *pStr == (GLubyte)'\0'))
else if(LastWasNumber && (*pStr == '.' || *pStr == ' ' || *pStr == '\0'))
{
int CurNumber = 0;
if(CurNumberStrLen > 0)
@ -3783,7 +3783,7 @@ static void ParseVersionString(const GLubyte *pStr, int &VersionMajor, int &Vers
LastWasNumber = false;
if(*pStr != (GLubyte)'.')
if(*pStr != '.')
break;
}
else
@ -3800,81 +3800,6 @@ static void ParseVersionString(const GLubyte *pStr, int &VersionMajor, int &Vers
}
}
/* TODO: move this somewhere nice, generalize it more for other drivers / vendors */
struct SBackEndDriverBlockList
{
int m_VersionIdentifierMin;
int m_VersionIdentifierMax;
int m_VersionMajorMin;
int m_VersionMajorMax;
int m_VersionMinorMin;
int m_VersionMinorMax;
int m_VersionPatchMin;
int m_VersionPatchMax;
const char *m_pReason;
};
static SBackEndDriverBlockList gs_aBlockList[] = {
{26, 26, 20, 20, 100, 100, 7800, 7999, "This Intel driver version can cause crashes, please update it to a newer version and remove any gfx_opengl* config from ddnet_settings.cfg."}};
static const char *ParseBlocklistDriverVersions(const GLubyte *pVendorStrGL, const GLubyte *pVersionStrGL)
{
if(str_find_nocase((const char *)pVendorStrGL, "Intel") == NULL)
return NULL;
const char *pVersionStrStart = str_find_nocase((const char *)pVersionStrGL, "Build ");
if(pVersionStrStart == NULL)
return NULL;
// ignore "Build ", after that, it should directly start with the driver version
pVersionStrStart += (ptrdiff_t)str_length("Build ");
// get the "major" version
char aVersionStrHelper[512]; // the size is random, but shouldn't be too small probably
const char *pIdentifier = str_next_token(pVersionStrStart, ".", aVersionStrHelper, sizeof(aVersionStrHelper));
if(pIdentifier == NULL)
return NULL;
pVersionStrStart = pIdentifier;
int VIdentifier = str_toint(aVersionStrHelper);
const char *pMajor = str_next_token(pVersionStrStart, ".", aVersionStrHelper, sizeof(aVersionStrHelper));
if(pMajor == NULL)
return NULL;
pVersionStrStart = pMajor;
int VMajor = str_toint(aVersionStrHelper);
const char *pMinor = str_next_token(pVersionStrStart, ".", aVersionStrHelper, sizeof(aVersionStrHelper));
if(pMinor == NULL)
return NULL;
pVersionStrStart = pMinor;
int VMinor = str_toint(aVersionStrHelper);
const char *pPatch = str_next_token(pVersionStrStart, ".", aVersionStrHelper, sizeof(aVersionStrHelper));
if(pPatch == NULL)
return NULL;
int VPatch = str_toint(aVersionStrHelper);
for(auto &BlockListItem : gs_aBlockList)
{
if(VIdentifier < BlockListItem.m_VersionIdentifierMin || VIdentifier > BlockListItem.m_VersionIdentifierMax)
continue;
if(VMajor < BlockListItem.m_VersionMajorMin || VMajor > BlockListItem.m_VersionMajorMax)
continue;
if(VMinor < BlockListItem.m_VersionMinorMin || VMinor > BlockListItem.m_VersionMinorMax)
continue;
if(VPatch < BlockListItem.m_VersionPatchMin || VPatch > BlockListItem.m_VersionPatchMax)
continue;
return BlockListItem.m_pReason;
}
return NULL;
}
static const char *GetGLErrorName(GLenum Type)
{
if(Type == GL_DEBUG_TYPE_ERROR)
@ -3961,12 +3886,12 @@ void CCommandProcessorFragment_SDL::Cmd_Init(const SCommand_Init *pCommand)
dbg_msg("gfx", "Requested OpenGL debug mode, but the driver does not support the required extension");
}
const GLubyte *pVendorString = glGetString(GL_VENDOR);
dbg_msg("opengl", "Vendor string: %s", (const char *)pVendorString);
const char *pVendorString = (const char *)glGetString(GL_VENDOR);
dbg_msg("opengl", "Vendor string: %s", pVendorString);
// check what this context can do
const GLubyte *pVersionString = glGetString(GL_VERSION);
dbg_msg("opengl", "Version string: %s", (const char *)pVersionString);
const char *pVersionString = (const char *)glGetString(GL_VERSION);
dbg_msg("opengl", "Version string: %s", pVersionString);
// parse version string
ParseVersionString(pVersionString, pCommand->m_pCapabilities->m_ContextMajor, pCommand->m_pCapabilities->m_ContextMinor, pCommand->m_pCapabilities->m_ContextPatch);

View file

@ -4,6 +4,7 @@
#include "SDL.h"
#include "SDL_opengl.h"
#include "blocklist_driver.h"
#include "graphics_threaded.h"
#include <base/tl/threading.h>

View file

@ -0,0 +1,66 @@
#include "blocklist_driver.h"
#include <base/system.h>
#define VERSION_PARTS 4
struct SVersion
{
int m_Parts[VERSION_PARTS];
bool operator<=(const SVersion &Other) const
{
for(int i = 0; i < VERSION_PARTS; i++)
{
if(m_Parts[i] < Other.m_Parts[i])
return true;
if(m_Parts[i] > Other.m_Parts[i])
return false;
}
return true;
}
};
/* TODO: generalize it more for other drivers / vendors */
struct SBackEndDriverBlockList
{
SVersion m_VersionMin;
SVersion m_VersionMax;
const char *m_pReason;
};
static SBackEndDriverBlockList gs_aBlockList[] = {
{{26, 20, 100, 7800}, {26, 20, 100, 7999}, "This Intel driver version can cause crashes, please update it to a newer version and remove any gfx_opengl* config from ddnet_settings.cfg."}};
const char *ParseBlocklistDriverVersions(const char *pVendorStr, const char *pVersionStr)
{
if(str_find_nocase(pVendorStr, "Intel") == NULL)
return NULL;
const char *pVersionStrStart = str_find_nocase(pVersionStr, "Build ");
if(pVersionStrStart == NULL)
return NULL;
// ignore "Build ", after that, it should directly start with the driver version
pVersionStrStart += (ptrdiff_t)str_length("Build ");
char aVersionStrHelper[512]; // the size is random, but shouldn't be too small probably
SVersion Version;
for(int &VersionPart : Version.m_Parts)
{
pVersionStrStart = str_next_token(pVersionStrStart, ".", aVersionStrHelper, sizeof(aVersionStrHelper));
if(pVersionStrStart == NULL)
return NULL;
VersionPart = str_toint(aVersionStrHelper);
}
for(const auto &BlockListItem : gs_aBlockList)
{
if(BlockListItem.m_VersionMin <= Version && Version <= BlockListItem.m_VersionMax)
return BlockListItem.m_pReason;
}
return NULL;
}

View file

@ -0,0 +1,6 @@
#ifndef ENGINE_CLIENT_BLOCKLIST_DRIVER_H
#define ENGINE_CLIENT_BLOCKLIST_DRIVER_H
const char *ParseBlocklistDriverVersions(const char *pVendorStr, const char *pVersionStr);
#endif // ENGINE_CLIENT_BLOCKLIST_DRIVER_H

View file

@ -0,0 +1,18 @@
#include <gtest/gtest.h>
#include <engine/client/blocklist_driver.h>
TEST(BlocklistDriver, Valid)
{
EXPECT_STREQ(ParseBlocklistDriverVersions("Intel", "Build 26.20.100.7810"), "This Intel driver version can cause crashes, please update it to a newer version and remove any gfx_opengl* config from ddnet_settings.cfg.");
EXPECT_STREQ(ParseBlocklistDriverVersions("Intel", "Build 26.20.100.7926"), "This Intel driver version can cause crashes, please update it to a newer version and remove any gfx_opengl* config from ddnet_settings.cfg.");
EXPECT_STREQ(ParseBlocklistDriverVersions("Intel", "Build 26.20.100.7985"), "This Intel driver version can cause crashes, please update it to a newer version and remove any gfx_opengl* config from ddnet_settings.cfg.");
}
TEST(BlocklistDriver, Invalid)
{
EXPECT_STREQ(ParseBlocklistDriverVersions("Intel", "Build 25.20.100.7810"), NULL);
EXPECT_STREQ(ParseBlocklistDriverVersions("Intel", "Build 26.20.100.7799"), NULL);
EXPECT_STREQ(ParseBlocklistDriverVersions("Intel", "Build 26.20.100.8000"), NULL);
EXPECT_STREQ(ParseBlocklistDriverVersions("Intel", "Build 27.20.100.7900"), NULL);
}