gex-gl: host GL tests run one at a time

They share the native decoder's process-wide name tables, so in the
parallel workspace run two tests mapped each other's framebuffer names
and one failed (3 runs in 15 on master ac269692; the coordinator's gate
hit protocol_12). A test-only mutex serialises the nine tests that make a
host context; 0 failures in 15 parallel runs.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_d2453757b8a84fdbb4ee7c9e093141df
This commit is contained in:
velzieandClaude Opus 5.5 committed 2026-10-08 11:05:57 -04:00
1 parent e204fa1b68
commit 7d7e45a85e
1 file changed
+18
+18
View File
@@ -1874,6 +1874,15 @@ impl Header {
#[cfg(test)]
mod tests {
use super::*;
/// One host GL test at a time: they share the native decoder's name
/// tables (gexgl_native_name/gexgl_native_object, process-wide), so two
/// running in parallel mapped each other's framebuffer names and the
/// parallel workspace run flaked (3 runs in 15 on master ac269692).
fn gl_lock() -> std::sync::MutexGuard<'static, ()> {
static LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
LOCK.lock().unwrap_or_else(|e| e.into_inner())
}
use crate::proto::{client_api, op, Batch};
// The handful of GL constants a test needs, spelled out rather than
@@ -1909,6 +1918,7 @@ mod tests {
/// the host's GL: Retrocycles crashed Mesa that way).
#[test]
fn client_side_indices_come_with_the_draw() {
let _serial = gl_lock();
let mut gl = match Gl::new(64, 64) {
Ok(g) => g,
Err(e) => {
@@ -1969,6 +1979,7 @@ mod tests {
/// thread that made it, and `cargo test` runs threads in parallel.
#[test]
fn a_command_stream_draws_a_triangle_and_reads_it_back() {
let _serial = gl_lock();
let mut gl = match Gl::new(64, 64) {
Ok(g) => g,
Err(e) => {
@@ -2072,6 +2083,7 @@ mod tests {
#[test]
fn a_shader_that_does_not_compile_says_why() {
let _serial = gl_lock();
let mut gl = match Gl::new(16, 16) {
Ok(g) => g,
Err(_) => return,
@@ -2094,6 +2106,7 @@ mod tests {
#[test]
fn an_unknown_opcode_stops_the_batch_rather_than_being_skipped() {
let _serial = gl_lock();
let mut gl = match Gl::new(16, 16) {
Ok(g) => g,
Err(_) => return,
@@ -2121,6 +2134,7 @@ mod tests {
/// mode, the matrix stack and display lists all run.
#[test]
fn a_desktop_context_runs_fixed_function() {
let _serial = gl_lock();
let mut gl = match Gl::new(16, 16) {
Ok(g) => g,
Err(e) => {
@@ -2183,6 +2197,7 @@ mod tests {
/// guest chose.
#[test]
fn a_framebuffer_object_renders_to_a_texture() {
let _serial = gl_lock();
let mut gl = match Gl::new(16, 16) {
Ok(g) => g,
Err(e) => {
@@ -2228,6 +2243,7 @@ mod tests {
/// answer with the guest's names.
#[test]
fn a_desktop_context_takes_framebuffer_names_it_never_generated() {
let _serial = gl_lock();
let mut gl = match Gl::new(16, 16) {
Ok(g) => g,
Err(e) => {
@@ -2295,6 +2311,7 @@ mod tests {
/// and scaling, a loaded matrix, the current color and the alpha test.
#[test]
fn protocol_11_client_arrays_and_fixed_function_matrices() {
let _serial = gl_lock();
let mut gl = match Gl::new(16, 16) {
Ok(g) => g,
Err(e) => {
@@ -2452,6 +2469,7 @@ mod tests {
/// separate blend functions (opcodes that already existed).
#[test]
fn protocol_12_attribute_stack_and_uniform_vectors() {
let _serial = gl_lock();
let mut gl = match Gl::new(16, 16) {
Ok(g) => g,
Err(e) => {