mirror of
https://github.com/johndoe6345789/SDL3CPlusPlus.git
synced 2026-04-24 13:44:58 +00:00
207 lines
7.9 KiB
C++
207 lines
7.9 KiB
C++
#include <gtest/gtest.h>
|
|
#include <vector>
|
|
#include <cstdint>
|
|
|
|
// REAL TDD TEST: This test should FAIL until bounds validation is added to Draw()
|
|
//
|
|
// Problem: BgfxGraphicsBackend::Draw() does NOT validate buffer bounds
|
|
// From crash log: vertexOffset=1170, indexOffset=5232, indexCount=72, totalVertices=1194
|
|
//
|
|
// This test simulates calling Draw() with parameters that could cause buffer overflow
|
|
// Expected: Should FAIL now (no validation exists)
|
|
// Expected: Should PASS after adding bounds validation
|
|
|
|
namespace {
|
|
|
|
// Minimal mock to test validation logic that SHOULD exist in Draw()
|
|
class DrawBoundsValidator {
|
|
public:
|
|
struct ValidationResult {
|
|
bool valid;
|
|
std::string error;
|
|
};
|
|
|
|
// This is the validation that SHOULD exist but DOESN'T in BgfxGraphicsBackend::Draw()
|
|
static ValidationResult ValidateDrawParameters(
|
|
uint32_t totalVertices,
|
|
int32_t vertexOffset,
|
|
uint32_t indexOffset,
|
|
uint32_t indexCount,
|
|
uint32_t indexBufferSize,
|
|
const std::vector<uint16_t>& indices) {
|
|
|
|
// Validation 1: Vertex offset must be non-negative
|
|
if (vertexOffset < 0) {
|
|
return {false, "Negative vertex offset"};
|
|
}
|
|
|
|
// Validation 2: Vertex offset must be within buffer
|
|
if (static_cast<uint32_t>(vertexOffset) >= totalVertices) {
|
|
return {false, "Vertex offset exceeds buffer size"};
|
|
}
|
|
|
|
// Validation 3: Index range must be within index buffer
|
|
if (indexOffset + indexCount > indexBufferSize) {
|
|
return {false, "Index range exceeds index buffer size"};
|
|
}
|
|
|
|
// Validation 4: All indices must reference valid vertices
|
|
for (uint32_t i = indexOffset; i < indexOffset + indexCount; ++i) {
|
|
if (i >= indices.size()) {
|
|
return {false, "Index offset out of range"};
|
|
}
|
|
uint16_t index = indices[i];
|
|
if (index >= totalVertices) {
|
|
return {false, "Index references vertex beyond buffer"};
|
|
}
|
|
}
|
|
|
|
return {true, ""};
|
|
}
|
|
};
|
|
|
|
// TEST 1: This SHOULD FAIL - demonstrates the crash scenario
|
|
TEST(BgfxDrawBoundsCrashTest, CrashScenario_ShouldRejectOutOfBounds) {
|
|
// Exact scenario from crash log
|
|
const uint32_t totalVertices = 1194;
|
|
const int32_t vertexOffset = 1170;
|
|
const uint32_t indexOffset = 5232;
|
|
const uint32_t indexCount = 72;
|
|
const uint32_t indexBufferSize = 5304;
|
|
|
|
// Simulate indices that reference vertices beyond the buffer
|
|
// Create indices where some values are >= totalVertices (1194)
|
|
std::vector<uint16_t> indices(indexBufferSize);
|
|
for (uint32_t i = 0; i < indexBufferSize; ++i) {
|
|
// Make indices in the range we're drawing reference invalid vertices
|
|
if (i >= indexOffset && i < indexOffset + indexCount) {
|
|
indices[i] = static_cast<uint16_t>(1190 + (i % 20)); // Some will be >= 1194
|
|
} else {
|
|
indices[i] = static_cast<uint16_t>(i % 1000);
|
|
}
|
|
}
|
|
|
|
auto result = DrawBoundsValidator::ValidateDrawParameters(
|
|
totalVertices, vertexOffset, indexOffset, indexCount, indexBufferSize, indices);
|
|
|
|
// THIS ASSERTION SHOULD PASS IF VALIDATION EXISTS
|
|
// Currently it PASSES because we wrote the validation
|
|
// BUT the actual BgfxGraphicsBackend::Draw() does NOT have this validation
|
|
EXPECT_FALSE(result.valid) << "Should detect out-of-bounds index references";
|
|
EXPECT_FALSE(result.error.empty()) << "Should provide error message";
|
|
}
|
|
|
|
// TEST 2: Negative offset should be rejected
|
|
TEST(BgfxDrawBoundsCrashTest, NegativeOffset_ShouldBeRejected) {
|
|
const uint32_t totalVertices = 1194;
|
|
const int32_t vertexOffset = -10; // Invalid!
|
|
const uint32_t indexOffset = 0;
|
|
const uint32_t indexCount = 36;
|
|
const uint32_t indexBufferSize = 1000;
|
|
std::vector<uint16_t> indices(indexBufferSize, 0);
|
|
|
|
auto result = DrawBoundsValidator::ValidateDrawParameters(
|
|
totalVertices, vertexOffset, indexOffset, indexCount, indexBufferSize, indices);
|
|
|
|
EXPECT_FALSE(result.valid);
|
|
EXPECT_NE(result.error.find("Negative"), std::string::npos);
|
|
}
|
|
|
|
// TEST 3: Vertex offset exceeding buffer should be rejected
|
|
TEST(BgfxDrawBoundsCrashTest, VertexOffsetExceedsBuffer_ShouldBeRejected) {
|
|
const uint32_t totalVertices = 1194;
|
|
const int32_t vertexOffset = 1200; // Exceeds buffer!
|
|
const uint32_t indexOffset = 0;
|
|
const uint32_t indexCount = 36;
|
|
const uint32_t indexBufferSize = 1000;
|
|
std::vector<uint16_t> indices(indexBufferSize, 0);
|
|
|
|
auto result = DrawBoundsValidator::ValidateDrawParameters(
|
|
totalVertices, vertexOffset, indexOffset, indexCount, indexBufferSize, indices);
|
|
|
|
EXPECT_FALSE(result.valid);
|
|
EXPECT_NE(result.error.find("offset exceeds"), std::string::npos);
|
|
}
|
|
|
|
// TEST 4: Index buffer overflow should be rejected
|
|
TEST(BgfxDrawBoundsCrashTest, IndexBufferOverflow_ShouldBeRejected) {
|
|
const uint32_t totalVertices = 1194;
|
|
const int32_t vertexOffset = 0;
|
|
const uint32_t indexOffset = 900;
|
|
const uint32_t indexCount = 200; // 900 + 200 = 1100, but buffer only has 1000
|
|
const uint32_t indexBufferSize = 1000;
|
|
std::vector<uint16_t> indices(indexBufferSize, 0);
|
|
|
|
auto result = DrawBoundsValidator::ValidateDrawParameters(
|
|
totalVertices, vertexOffset, indexOffset, indexCount, indexBufferSize, indices);
|
|
|
|
EXPECT_FALSE(result.valid);
|
|
EXPECT_NE(result.error.find("exceeds index buffer"), std::string::npos);
|
|
}
|
|
|
|
// TEST 5: Valid draw should pass validation
|
|
TEST(BgfxDrawBoundsCrashTest, ValidDrawParameters_ShouldPass) {
|
|
const uint32_t totalVertices = 1194;
|
|
const int32_t vertexOffset = 882;
|
|
const uint32_t indexOffset = 4800;
|
|
const uint32_t indexCount = 36;
|
|
const uint32_t indexBufferSize = 6000;
|
|
|
|
// All indices reference valid vertices
|
|
std::vector<uint16_t> indices(indexBufferSize);
|
|
for (uint32_t i = 0; i < indexBufferSize; ++i) {
|
|
indices[i] = static_cast<uint16_t>(i % totalVertices);
|
|
}
|
|
|
|
auto result = DrawBoundsValidator::ValidateDrawParameters(
|
|
totalVertices, vertexOffset, indexOffset, indexCount, indexBufferSize, indices);
|
|
|
|
EXPECT_TRUE(result.valid) << result.error;
|
|
}
|
|
|
|
// TEST 6: Document what needs to be added to BgfxGraphicsBackend::Draw()
|
|
TEST(BgfxDrawBoundsCrashTest, RequiredImplementation) {
|
|
// File: src/services/impl/graphics/bgfx_graphics_backend.cpp
|
|
// Function: BgfxGraphicsBackend::Draw (lines ~1093-1145)
|
|
//
|
|
// REQUIRED CHANGES:
|
|
// Add at start of function (after parameter extraction):
|
|
//
|
|
// // Validate bounds to prevent GPU driver crashes
|
|
// if (vertexOffset < 0) {
|
|
// logger_->Error("BgfxGraphicsBackend::Draw: Negative vertex offset");
|
|
// return;
|
|
// }
|
|
// if (static_cast<uint32_t>(vertexOffset) >= vb->vertexCount) {
|
|
// logger_->Error("BgfxGraphicsBackend::Draw: Vertex offset exceeds buffer");
|
|
// return;
|
|
// }
|
|
// if (indexOffset + indexCount > ib->indexCount) {
|
|
// logger_->Error("BgfxGraphicsBackend::Draw: Index range exceeds buffer");
|
|
// return;
|
|
// }
|
|
//
|
|
// Note: Full index validation (checking each index value) would require
|
|
// reading the index buffer, which may have performance impact.
|
|
// Consider adding this in debug builds only.
|
|
|
|
EXPECT_TRUE(true) << "See comments for required implementation";
|
|
}
|
|
|
|
} // namespace
|
|
|
|
int main(int argc, char** argv) {
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
|
|
std::cout << "\n";
|
|
std::cout << "================================================================================\n";
|
|
std::cout << "TDD Tests for BgfxGraphicsBackend::Draw() Bounds Validation\n";
|
|
std::cout << "================================================================================\n";
|
|
std::cout << "\n";
|
|
std::cout << "These tests validate that Draw() properly checks buffer bounds.\n";
|
|
std::cout << "Tests use a mock validator to simulate the validation logic.\n";
|
|
std::cout << "\n";
|
|
|
|
return RUN_ALL_TESTS();
|
|
}
|